diff options
author | root <root@ka-ata-killa.ourano.james.local> | 2021-02-24 23:45:58 +0000 |
---|---|---|
committer | root <root@ka-ata-killa.ourano.james.local> | 2021-02-24 23:45:58 +0000 |
commit | 1575d4f53805f177474b5bb96daebede9b2dfb73 (patch) | |
tree | 91f6819f7280088bb9344fae7dbef8c43a0a04c0 /de1/fpga-bbc-pq/master/line-endings.patch | |
download | base-master.tar.gz base-master.tar.bz2 base-master.zip |
Diffstat (limited to 'de1/fpga-bbc-pq/master/line-endings.patch')
-rw-r--r-- | de1/fpga-bbc-pq/master/line-endings.patch | 17558 |
1 files changed, 17558 insertions, 0 deletions
diff --git a/de1/fpga-bbc-pq/master/line-endings.patch b/de1/fpga-bbc-pq/master/line-endings.patch new file mode 100644 index 0000000..dd090b6 --- /dev/null +++ b/de1/fpga-bbc-pq/master/line-endings.patch @@ -0,0 +1,17558 @@ +diff --git a/CII_Starter_pin_assignments.csv b/CII_Starter_pin_assignments.csv +index f46adb0..3e1f8de 100644 +--- a/CII_Starter_pin_assignments.csv ++++ b/CII_Starter_pin_assignments.csv +@@ -1,455 +1,455 @@ +-
+-# Note: The column header names should not be changed if you wish to import this .csv file into the Quartus II software.
+-
+-From,To,Assignment Name,Value,Enabled
+-,GPIO_0[0],Location,PIN_A13,Yes
+-,GPIO_0[1],Location,PIN_B13,Yes
+-,GPIO_0[2],Location,PIN_A14,Yes
+-,GPIO_0[3],Location,PIN_B14,Yes
+-,GPIO_0[4],Location,PIN_A15,Yes
+-,GPIO_0[5],Location,PIN_B15,Yes
+-,GPIO_0[6],Location,PIN_A16,Yes
+-,GPIO_0[7],Location,PIN_B16,Yes
+-,GPIO_0[8],Location,PIN_A17,Yes
+-,GPIO_0[9],Location,PIN_B17,Yes
+-,GPIO_0[10],Location,PIN_A18,Yes
+-,GPIO_0[11],Location,PIN_B18,Yes
+-,GPIO_0[12],Location,PIN_A19,Yes
+-,GPIO_0[13],Location,PIN_B19,Yes
+-,GPIO_0[14],Location,PIN_A20,Yes
+-,GPIO_0[15],Location,PIN_B20,Yes
+-,GPIO_0[16],Location,PIN_C21,Yes
+-,GPIO_0[17],Location,PIN_C22,Yes
+-,GPIO_0[18],Location,PIN_D21,Yes
+-,GPIO_0[19],Location,PIN_D22,Yes
+-,GPIO_0[20],Location,PIN_E21,Yes
+-,GPIO_0[21],Location,PIN_E22,Yes
+-,GPIO_0[22],Location,PIN_F21,Yes
+-,GPIO_0[23],Location,PIN_F22,Yes
+-,GPIO_0[24],Location,PIN_G21,Yes
+-,GPIO_0[25],Location,PIN_G22,Yes
+-,GPIO_0[26],Location,PIN_J21,Yes
+-,GPIO_0[27],Location,PIN_J22,Yes
+-,GPIO_0[28],Location,PIN_K21,Yes
+-,GPIO_0[29],Location,PIN_K22,Yes
+-,GPIO_0[30],Location,PIN_J19,Yes
+-,GPIO_0[31],Location,PIN_J20,Yes
+-,GPIO_0[32],Location,PIN_J18,Yes
+-,GPIO_0[33],Location,PIN_K20,Yes
+-,GPIO_0[34],Location,PIN_L19,Yes
+-,GPIO_0[35],Location,PIN_L18,Yes
+-,GPIO_1[0],Location,PIN_H12,Yes
+-,GPIO_1[1],Location,PIN_H13,Yes
+-,GPIO_1[2],Location,PIN_H14,Yes
+-,GPIO_1[3],Location,PIN_G15,Yes
+-,GPIO_1[4],Location,PIN_E14,Yes
+-,GPIO_1[5],Location,PIN_E15,Yes
+-,GPIO_1[6],Location,PIN_F15,Yes
+-,GPIO_1[7],Location,PIN_G16,Yes
+-,GPIO_1[8],Location,PIN_F12,Yes
+-,GPIO_1[9],Location,PIN_F13,Yes
+-,GPIO_1[10],Location,PIN_C14,Yes
+-,GPIO_1[11],Location,PIN_D14,Yes
+-,GPIO_1[12],Location,PIN_D15,Yes
+-,GPIO_1[13],Location,PIN_D16,Yes
+-,GPIO_1[14],Location,PIN_C17,Yes
+-,GPIO_1[15],Location,PIN_C18,Yes
+-,GPIO_1[16],Location,PIN_C19,Yes
+-,GPIO_1[17],Location,PIN_C20,Yes
+-,GPIO_1[18],Location,PIN_D19,Yes
+-,GPIO_1[19],Location,PIN_D20,Yes
+-,GPIO_1[20],Location,PIN_E20,Yes
+-,GPIO_1[21],Location,PIN_F20,Yes
+-,GPIO_1[22],Location,PIN_E19,Yes
+-,GPIO_1[23],Location,PIN_E18,Yes
+-,GPIO_1[24],Location,PIN_G20,Yes
+-,GPIO_1[25],Location,PIN_G18,Yes
+-,GPIO_1[26],Location,PIN_G17,Yes
+-,GPIO_1[27],Location,PIN_H17,Yes
+-,GPIO_1[28],Location,PIN_J15,Yes
+-,GPIO_1[29],Location,PIN_H18,Yes
+-,GPIO_1[30],Location,PIN_N22,Yes
+-,GPIO_1[31],Location,PIN_N21,Yes
+-,GPIO_1[32],Location,PIN_P15,Yes
+-,GPIO_1[33],Location,PIN_N15,Yes
+-,GPIO_1[34],Location,PIN_P17,Yes
+-,GPIO_1[35],Location,PIN_P18,Yes
+-,GPIO_0[0],I/O Standard,LVTTL,Yes
+-,GPIO_0[1],I/O Standard,LVTTL,Yes
+-,GPIO_0[2],I/O Standard,LVTTL,Yes
+-,GPIO_0[3],I/O Standard,LVTTL,Yes
+-,GPIO_0[4],I/O Standard,LVTTL,Yes
+-,GPIO_0[5],I/O Standard,LVTTL,Yes
+-,GPIO_0[6],I/O Standard,LVTTL,Yes
+-,GPIO_0[7],I/O Standard,LVTTL,Yes
+-,GPIO_0[8],I/O Standard,LVTTL,Yes
+-,GPIO_0[9],I/O Standard,LVTTL,Yes
+-,GPIO_0[10],I/O Standard,LVTTL,Yes
+-,GPIO_0[11],I/O Standard,LVTTL,Yes
+-,GPIO_0[12],I/O Standard,LVTTL,Yes
+-,GPIO_0[13],I/O Standard,LVTTL,Yes
+-,GPIO_0[14],I/O Standard,LVTTL,Yes
+-,GPIO_0[15],I/O Standard,LVTTL,Yes
+-,GPIO_0[16],I/O Standard,LVTTL,Yes
+-,GPIO_0[17],I/O Standard,LVTTL,Yes
+-,GPIO_0[18],I/O Standard,LVTTL,Yes
+-,GPIO_0[19],I/O Standard,LVTTL,Yes
+-,GPIO_0[20],I/O Standard,LVTTL,Yes
+-,GPIO_0[21],I/O Standard,LVTTL,Yes
+-,GPIO_0[22],I/O Standard,LVTTL,Yes
+-,GPIO_0[23],I/O Standard,LVTTL,Yes
+-,GPIO_0[24],I/O Standard,LVTTL,Yes
+-,GPIO_0[25],I/O Standard,LVTTL,Yes
+-,GPIO_0[26],I/O Standard,LVTTL,Yes
+-,GPIO_0[27],I/O Standard,LVTTL,Yes
+-,GPIO_0[28],I/O Standard,LVTTL,Yes
+-,GPIO_0[29],I/O Standard,LVTTL,Yes
+-,GPIO_0[30],I/O Standard,LVTTL,Yes
+-,GPIO_0[31],I/O Standard,LVTTL,Yes
+-,GPIO_0[32],I/O Standard,LVTTL,Yes
+-,GPIO_0[33],I/O Standard,LVTTL,Yes
+-,GPIO_0[34],I/O Standard,LVTTL,Yes
+-,GPIO_0[35],I/O Standard,LVTTL,Yes
+-,GPIO_1[0],I/O Standard,LVTTL,Yes
+-,GPIO_1[1],I/O Standard,LVTTL,Yes
+-,GPIO_1[2],I/O Standard,LVTTL,Yes
+-,GPIO_1[3],I/O Standard,LVTTL,Yes
+-,GPIO_1[4],I/O Standard,LVTTL,Yes
+-,GPIO_1[5],I/O Standard,LVTTL,Yes
+-,GPIO_1[6],I/O Standard,LVTTL,Yes
+-,GPIO_1[7],I/O Standard,LVTTL,Yes
+-,GPIO_1[8],I/O Standard,LVTTL,Yes
+-,GPIO_1[9],I/O Standard,LVTTL,Yes
+-,GPIO_1[10],I/O Standard,LVTTL,Yes
+-,GPIO_1[11],I/O Standard,LVTTL,Yes
+-,GPIO_1[12],I/O Standard,LVTTL,Yes
+-,GPIO_1[13],I/O Standard,LVTTL,Yes
+-,GPIO_1[14],I/O Standard,LVTTL,Yes
+-,GPIO_1[15],I/O Standard,LVTTL,Yes
+-,GPIO_1[16],I/O Standard,LVTTL,Yes
+-,GPIO_1[17],I/O Standard,LVTTL,Yes
+-,GPIO_1[18],I/O Standard,LVTTL,Yes
+-,GPIO_1[19],I/O Standard,LVTTL,Yes
+-,GPIO_1[20],I/O Standard,LVTTL,Yes
+-,GPIO_1[21],I/O Standard,LVTTL,Yes
+-,GPIO_1[22],I/O Standard,LVTTL,Yes
+-,GPIO_1[23],I/O Standard,LVTTL,Yes
+-,GPIO_1[24],I/O Standard,LVTTL,Yes
+-,GPIO_1[25],I/O Standard,LVTTL,Yes
+-,GPIO_1[26],I/O Standard,LVTTL,Yes
+-,GPIO_1[27],I/O Standard,LVTTL,Yes
+-,GPIO_1[28],I/O Standard,LVTTL,Yes
+-,GPIO_1[29],I/O Standard,LVTTL,Yes
+-,GPIO_1[30],I/O Standard,LVTTL,Yes
+-,GPIO_1[31],I/O Standard,LVTTL,Yes
+-,GPIO_1[32],I/O Standard,LVTTL,Yes
+-,GPIO_1[33],I/O Standard,LVTTL,Yes
+-,GPIO_1[34],I/O Standard,LVTTL,Yes
+-,GPIO_1[35],I/O Standard,LVTTL,Yes
+-,SW[0],Location,PIN_L22,Yes
+-,SW[1],Location,PIN_L21,Yes
+-,SW[2],Location,PIN_M22,Yes
+-,SW[3],Location,PIN_V12,Yes
+-,SW[4],Location,PIN_W12,Yes
+-,SW[5],Location,PIN_U12,Yes
+-,SW[6],Location,PIN_U11,Yes
+-,SW[7],Location,PIN_M2,Yes
+-,SW[8],Location,PIN_M1,Yes
+-,SW[9],Location,PIN_L2,Yes
+-,SW[0],I/O Standard,LVTTL,Yes
+-,SW[1],I/O Standard,LVTTL,Yes
+-,SW[2],I/O Standard,LVTTL,Yes
+-,SW[3],I/O Standard,LVTTL,Yes
+-,SW[4],I/O Standard,LVTTL,Yes
+-,SW[5],I/O Standard,LVTTL,Yes
+-,SW[6],I/O Standard,LVTTL,Yes
+-,SW[7],I/O Standard,LVTTL,Yes
+-,SW[8],I/O Standard,LVTTL,Yes
+-,SW[9],I/O Standard,LVTTL,Yes
+-,HEX0[0],Location,PIN_J2,Yes
+-,HEX0[1],Location,PIN_J1,Yes
+-,HEX0[2],Location,PIN_H2,Yes
+-,HEX0[3],Location,PIN_H1,Yes
+-,HEX0[4],Location,PIN_F2,Yes
+-,HEX0[5],Location,PIN_F1,Yes
+-,HEX0[6],Location,PIN_E2,Yes
+-,HEX1[0],Location,PIN_E1,Yes
+-,HEX1[1],Location,PIN_H6,Yes
+-,HEX1[2],Location,PIN_H5,Yes
+-,HEX1[3],Location,PIN_H4,Yes
+-,HEX1[4],Location,PIN_G3,Yes
+-,HEX1[5],Location,PIN_D2,Yes
+-,HEX1[6],Location,PIN_D1,Yes
+-,HEX2[0],Location,PIN_G5,Yes
+-,HEX2[1],Location,PIN_G6,Yes
+-,HEX2[2],Location,PIN_C2,Yes
+-,HEX2[3],Location,PIN_C1,Yes
+-,HEX2[4],Location,PIN_E3,Yes
+-,HEX2[5],Location,PIN_E4,Yes
+-,HEX2[6],Location,PIN_D3,Yes
+-,HEX3[0],Location,PIN_F4,Yes
+-,HEX3[1],Location,PIN_D5,Yes
+-,HEX3[2],Location,PIN_D6,Yes
+-,HEX3[3],Location,PIN_J4,Yes
+-,HEX3[4],Location,PIN_L8,Yes
+-,HEX3[5],Location,PIN_F3,Yes
+-,HEX3[6],Location,PIN_D4,Yes
+-,HEX0[0],I/O Standard,LVTTL,Yes
+-,HEX0[1],I/O Standard,LVTTL,Yes
+-,HEX0[2],I/O Standard,LVTTL,Yes
+-,HEX0[3],I/O Standard,LVTTL,Yes
+-,HEX0[4],I/O Standard,LVTTL,Yes
+-,HEX0[5],I/O Standard,LVTTL,Yes
+-,HEX0[6],I/O Standard,LVTTL,Yes
+-,HEX1[0],I/O Standard,LVTTL,Yes
+-,HEX1[1],I/O Standard,LVTTL,Yes
+-,HEX1[2],I/O Standard,LVTTL,Yes
+-,HEX1[3],I/O Standard,LVTTL,Yes
+-,HEX1[4],I/O Standard,LVTTL,Yes
+-,HEX1[5],I/O Standard,LVTTL,Yes
+-,HEX1[6],I/O Standard,LVTTL,Yes
+-,HEX2[0],I/O Standard,LVTTL,Yes
+-,HEX2[1],I/O Standard,LVTTL,Yes
+-,HEX2[2],I/O Standard,LVTTL,Yes
+-,HEX2[3],I/O Standard,LVTTL,Yes
+-,HEX2[4],I/O Standard,LVTTL,Yes
+-,HEX2[5],I/O Standard,LVTTL,Yes
+-,HEX2[6],I/O Standard,LVTTL,Yes
+-,HEX3[0],I/O Standard,LVTTL,Yes
+-,HEX3[1],I/O Standard,LVTTL,Yes
+-,HEX3[2],I/O Standard,LVTTL,Yes
+-,HEX3[3],I/O Standard,LVTTL,Yes
+-,HEX3[4],I/O Standard,LVTTL,Yes
+-,HEX3[5],I/O Standard,LVTTL,Yes
+-,HEX3[6],I/O Standard,LVTTL,Yes
+-,KEY[0],Location,PIN_R22,Yes
+-,KEY[1],Location,PIN_R21,Yes
+-,KEY[2],Location,PIN_T22,Yes
+-,KEY[3],Location,PIN_T21,Yes
+-,LEDR[0],Location,PIN_R20,Yes
+-,LEDR[1],Location,PIN_R19,Yes
+-,LEDR[2],Location,PIN_U19,Yes
+-,LEDR[3],Location,PIN_Y19,Yes
+-,LEDR[4],Location,PIN_T18,Yes
+-,LEDR[5],Location,PIN_V19,Yes
+-,LEDR[6],Location,PIN_Y18,Yes
+-,LEDR[7],Location,PIN_U18,Yes
+-,LEDR[8],Location,PIN_R18,Yes
+-,LEDR[9],Location,PIN_R17,Yes
+-,LEDG[0],Location,PIN_U22,Yes
+-,LEDG[1],Location,PIN_U21,Yes
+-,LEDG[2],Location,PIN_V22,Yes
+-,LEDG[3],Location,PIN_V21,Yes
+-,LEDG[4],Location,PIN_W22,Yes
+-,LEDG[5],Location,PIN_W21,Yes
+-,LEDG[6],Location,PIN_Y22,Yes
+-,LEDG[7],Location,PIN_Y21,Yes
+-,KEY[0],I/O Standard,LVTTL,Yes
+-,KEY[1],I/O Standard,LVTTL,Yes
+-,KEY[2],I/O Standard,LVTTL,Yes
+-,KEY[3],I/O Standard,LVTTL,Yes
+-,LEDR[0],I/O Standard,LVTTL,Yes
+-,LEDR[1],I/O Standard,LVTTL,Yes
+-,LEDR[2],I/O Standard,LVTTL,Yes
+-,LEDR[3],I/O Standard,LVTTL,Yes
+-,LEDR[4],I/O Standard,LVTTL,Yes
+-,LEDR[5],I/O Standard,LVTTL,Yes
+-,LEDR[6],I/O Standard,LVTTL,Yes
+-,LEDR[7],I/O Standard,LVTTL,Yes
+-,LEDR[8],I/O Standard,LVTTL,Yes
+-,LEDR[9],I/O Standard,LVTTL,Yes
+-,LEDG[0],I/O Standard,LVTTL,Yes
+-,LEDG[1],I/O Standard,LVTTL,Yes
+-,LEDG[2],I/O Standard,LVTTL,Yes
+-,LEDG[3],I/O Standard,LVTTL,Yes
+-,LEDG[4],I/O Standard,LVTTL,Yes
+-,LEDG[5],I/O Standard,LVTTL,Yes
+-,LEDG[6],I/O Standard,LVTTL,Yes
+-,LEDG[7],I/O Standard,LVTTL,Yes
+-,CLOCK_27[0],Location,PIN_D12,Yes
+-,CLOCK_27[1],Location,PIN_E12,Yes
+-,CLOCK_24[0],Location,PIN_B12,Yes
+-,CLOCK_24[1],Location,PIN_A12,Yes
+-,CLOCK_50,Location,PIN_L1,Yes
+-,EXT_CLOCK,Location,PIN_M21,Yes
+-,CLOCK_27[1],I/O Standard,LVTTL,Yes
+-,CLOCK_24[0],I/O Standard,LVTTL,Yes
+-,CLOCK_24[1],I/O Standard,LVTTL,Yes
+-,CLOCK_50,I/O Standard,LVTTL,Yes
+-,EXT_CLOCK,I/O Standard,LVTTL,Yes
+-,PS2_CLK,Location,PIN_H15,Yes
+-,PS2_DAT,Location,PIN_J14,Yes
+-,UART_RXD,Location,PIN_F14,Yes
+-,UART_TXD,Location,PIN_G12,Yes
+-,PS2_CLK,I/O Standard,LVTTL,Yes
+-,PS2_DAT,I/O Standard,LVTTL,Yes
+-,UART_RXD,I/O Standard,LVTTL,Yes
+-,UART_TXD,I/O Standard,LVTTL,Yes
+-,TDI,Location,PIN_E8,Yes
+-,TCS,Location,PIN_D8,Yes
+-,TCK,Location,PIN_C7,Yes
+-,TDO,Location,PIN_D7,Yes
+-,TDI,I/O Standard,LVTTL,Yes
+-,TCS,I/O Standard,LVTTL,Yes
+-,TCK,I/O Standard,LVTTL,Yes
+-,TDO,I/O Standard,LVTTL,Yes
+-,VGA_R[0],Location,PIN_D9,Yes
+-,VGA_R[1],Location,PIN_C9,Yes
+-,VGA_R[2],Location,PIN_A7,Yes
+-,VGA_R[3],Location,PIN_B7,Yes
+-,VGA_G[0],Location,PIN_B8,Yes
+-,VGA_G[1],Location,PIN_C10,Yes
+-,VGA_G[2],Location,PIN_B9,Yes
+-,VGA_G[3],Location,PIN_A8,Yes
+-,VGA_B[0],Location,PIN_A9,Yes
+-,VGA_B[1],Location,PIN_D11,Yes
+-,VGA_B[2],Location,PIN_A10,Yes
+-,VGA_B[3],Location,PIN_B10,Yes
+-,VGA_HS,Location,PIN_A11,Yes
+-,VGA_VS,Location,PIN_B11,Yes
+-,VGA_R[0],I/O Standard,LVTTL,Yes
+-,VGA_R[1],I/O Standard,LVTTL,Yes
+-,VGA_R[2],I/O Standard,LVTTL,Yes
+-,VGA_R[3],I/O Standard,LVTTL,Yes
+-,VGA_G[0],I/O Standard,LVTTL,Yes
+-,VGA_G[1],I/O Standard,LVTTL,Yes
+-,VGA_G[2],I/O Standard,LVTTL,Yes
+-,VGA_G[3],I/O Standard,LVTTL,Yes
+-,VGA_B[0],I/O Standard,LVTTL,Yes
+-,VGA_B[1],I/O Standard,LVTTL,Yes
+-,VGA_B[2],I/O Standard,LVTTL,Yes
+-,VGA_B[3],I/O Standard,LVTTL,Yes
+-,VGA_HS,I/O Standard,LVTTL,Yes
+-,VGA_VS,I/O Standard,LVTTL,Yes
+-,I2C_SCLK,Location,PIN_A3,Yes
+-,I2C_SDAT,Location,PIN_B3,Yes
+-,AUD_ADCLRCK,Location,PIN_A6,Yes
+-,AUD_ADCDAT,Location,PIN_B6,Yes
+-,AUD_DACLRCK,Location,PIN_A5,Yes
+-,AUD_DACDAT,Location,PIN_B5,Yes
+-,AUD_XCK,Location,PIN_B4,Yes
+-,AUD_BCLK,Location,PIN_A4,Yes
+-,I2C_SCLK,I/O Standard,LVTTL,Yes
+-,I2C_SDAT,I/O Standard,LVTTL,Yes
+-,AUD_ADCLRCK,I/O Standard,LVTTL,Yes
+-,AUD_ADCDAT,I/O Standard,LVTTL,Yes
+-,AUD_DACLRCK,I/O Standard,LVTTL,Yes
+-,AUD_DACDAT,I/O Standard,LVTTL,Yes
+-,AUD_XCK,I/O Standard,LVTTL,Yes
+-,AUD_BCLK,I/O Standard,LVTTL,Yes
+-,DRAM_ADDR[0],Location,PIN_W4,Yes
+-,DRAM_ADDR[1],Location,PIN_W5,Yes
+-,DRAM_ADDR[2],Location,PIN_Y3,Yes
+-,DRAM_ADDR[3],Location,PIN_Y4,Yes
+-,DRAM_ADDR[4],Location,PIN_R6,Yes
+-,DRAM_ADDR[5],Location,PIN_R5,Yes
+-,DRAM_ADDR[6],Location,PIN_P6,Yes
+-,DRAM_ADDR[7],Location,PIN_P5,Yes
+-,DRAM_ADDR[8],Location,PIN_P3,Yes
+-,DRAM_ADDR[9],Location,PIN_N4,Yes
+-,DRAM_ADDR[10],Location,PIN_W3,Yes
+-,DRAM_ADDR[11],Location,PIN_N6,Yes
+-,DRAM_BA_0,Location,PIN_U3,Yes
+-,DRAM_BA_1,Location,PIN_V4,Yes
+-,DRAM_CAS_N,Location,PIN_T3,Yes
+-,DRAM_CKE,Location,PIN_N3,Yes
+-,DRAM_CLK,Location,PIN_U4,Yes
+-,DRAM_CS_N,Location,PIN_T6,Yes
+-,DRAM_DQ[0],Location,PIN_U1,Yes
+-,DRAM_DQ[1],Location,PIN_U2,Yes
+-,DRAM_DQ[2],Location,PIN_V1,Yes
+-,DRAM_DQ[3],Location,PIN_V2,Yes
+-,DRAM_DQ[4],Location,PIN_W1,Yes
+-,DRAM_DQ[5],Location,PIN_W2,Yes
+-,DRAM_DQ[6],Location,PIN_Y1,Yes
+-,DRAM_DQ[7],Location,PIN_Y2,Yes
+-,DRAM_DQ[8],Location,PIN_N1,Yes
+-,DRAM_DQ[9],Location,PIN_N2,Yes
+-,DRAM_DQ[10],Location,PIN_P1,Yes
+-,DRAM_DQ[11],Location,PIN_P2,Yes
+-,DRAM_DQ[12],Location,PIN_R1,Yes
+-,DRAM_DQ[13],Location,PIN_R2,Yes
+-,DRAM_DQ[14],Location,PIN_T1,Yes
+-,DRAM_DQ[15],Location,PIN_T2,Yes
+-,DRAM_LDQM,Location,PIN_R7,Yes
+-,DRAM_RAS_N,Location,PIN_T5,Yes
+-,DRAM_UDQM,Location,PIN_M5,Yes
+-,DRAM_WE_N,Location,PIN_R8,Yes
+-,FL_ADDR[0],Location,PIN_AB20,Yes
+-,FL_ADDR[1],Location,PIN_AA14,Yes
+-,FL_ADDR[2],Location,PIN_Y16,Yes
+-,FL_ADDR[3],Location,PIN_R15,Yes
+-,FL_ADDR[4],Location,PIN_T15,Yes
+-,FL_ADDR[5],Location,PIN_U15,Yes
+-,FL_ADDR[6],Location,PIN_V15,Yes
+-,FL_ADDR[7],Location,PIN_W15,Yes
+-,FL_ADDR[8],Location,PIN_R14,Yes
+-,FL_ADDR[9],Location,PIN_Y13,Yes
+-,FL_ADDR[10],Location,PIN_R12,Yes
+-,FL_ADDR[11],Location,PIN_T12,Yes
+-,FL_ADDR[12],Location,PIN_AB14,Yes
+-,FL_ADDR[13],Location,PIN_AA13,Yes
+-,FL_ADDR[14],Location,PIN_AB13,Yes
+-,FL_ADDR[15],Location,PIN_AA12,Yes
+-,FL_ADDR[16],Location,PIN_AB12,Yes
+-,FL_ADDR[17],Location,PIN_AA20,Yes
+-,FL_ADDR[18],Location,PIN_U14,Yes
+-,FL_ADDR[19],Location,PIN_V14,Yes
+-,FL_ADDR[20],Location,PIN_U13,Yes
+-,FL_ADDR[21],Location,PIN_R13,Yes
+-,FL_DQ[0],Location,PIN_AB16,Yes
+-,FL_DQ[1],Location,PIN_AA16,Yes
+-,FL_DQ[2],Location,PIN_AB17,Yes
+-,FL_DQ[3],Location,PIN_AA17,Yes
+-,FL_DQ[4],Location,PIN_AB18,Yes
+-,FL_DQ[5],Location,PIN_AA18,Yes
+-,FL_DQ[6],Location,PIN_AB19,Yes
+-,FL_DQ[7],Location,PIN_AA19,Yes
+-,FL_OE_N,Location,PIN_AA15,Yes
+-,FL_RST_N,Location,PIN_W14,Yes
+-,FL_WE_N,Location,PIN_Y14,Yes
+-,FL_CE_N,Location,PIN_AB15,Yes
+-,SRAM_ADDR[0],Location,PIN_AA3,Yes
+-,SRAM_ADDR[1],Location,PIN_AB3,Yes
+-,SRAM_ADDR[2],Location,PIN_AA4,Yes
+-,SRAM_ADDR[3],Location,PIN_AB4,Yes
+-,SRAM_ADDR[4],Location,PIN_AA5,Yes
+-,SRAM_ADDR[5],Location,PIN_AB10,Yes
+-,SRAM_ADDR[6],Location,PIN_AA11,Yes
+-,SRAM_ADDR[7],Location,PIN_AB11,Yes
+-,SRAM_ADDR[8],Location,PIN_V11,Yes
+-,SRAM_ADDR[9],Location,PIN_W11,Yes
+-,SRAM_ADDR[10],Location,PIN_R11,Yes
+-,SRAM_ADDR[11],Location,PIN_T11,Yes
+-,SRAM_ADDR[12],Location,PIN_Y10,Yes
+-,SRAM_ADDR[13],Location,PIN_U10,Yes
+-,SRAM_ADDR[14],Location,PIN_R10,Yes
+-,SRAM_ADDR[15],Location,PIN_T7,Yes
+-,SRAM_ADDR[16],Location,PIN_Y6,Yes
+-,SRAM_ADDR[17],Location,PIN_Y5,Yes
+-,SRAM_CE_N,Location,PIN_AB5,Yes
+-,SRAM_DQ[0],Location,PIN_AA6,Yes
+-,SRAM_DQ[1],Location,PIN_AB6,Yes
+-,SRAM_DQ[2],Location,PIN_AA7,Yes
+-,SRAM_DQ[3],Location,PIN_AB7,Yes
+-,SRAM_DQ[4],Location,PIN_AA8,Yes
+-,SRAM_DQ[5],Location,PIN_AB8,Yes
+-,SRAM_DQ[6],Location,PIN_AA9,Yes
+-,SRAM_DQ[7],Location,PIN_AB9,Yes
+-,SRAM_DQ[8],Location,PIN_Y9,Yes
+-,SRAM_DQ[9],Location,PIN_W9,Yes
+-,SRAM_DQ[10],Location,PIN_V9,Yes
+-,SRAM_DQ[11],Location,PIN_U9,Yes
+-,SRAM_DQ[12],Location,PIN_R9,Yes
+-,SRAM_DQ[13],Location,PIN_W8,Yes
+-,SRAM_DQ[14],Location,PIN_V8,Yes
+-,SRAM_DQ[15],Location,PIN_U8,Yes
+-,SRAM_LB_N,Location,PIN_Y7,Yes
+-,SRAM_OE_N,Location,PIN_T8,Yes
+-,SRAM_UB_N,Location,PIN_W7,Yes
+-,SRAM_WE_N,Location,PIN_AA10,Yes
+-,SD_nCS,Location,PIN_U20,Yes
+-,SD_MOSI,Location,PIN_Y20,Yes
+-,SD_SCLK,Location,PIN_V20,Yes
+-,SD_MISO,Location,PIN_W20,Yes
+-
++ ++# Note: The column header names should not be changed if you wish to import this .csv file into the Quartus II software. ++ ++From,To,Assignment Name,Value,Enabled ++,GPIO_0[0],Location,PIN_A13,Yes ++,GPIO_0[1],Location,PIN_B13,Yes ++,GPIO_0[2],Location,PIN_A14,Yes ++,GPIO_0[3],Location,PIN_B14,Yes ++,GPIO_0[4],Location,PIN_A15,Yes ++,GPIO_0[5],Location,PIN_B15,Yes ++,GPIO_0[6],Location,PIN_A16,Yes ++,GPIO_0[7],Location,PIN_B16,Yes ++,GPIO_0[8],Location,PIN_A17,Yes ++,GPIO_0[9],Location,PIN_B17,Yes ++,GPIO_0[10],Location,PIN_A18,Yes ++,GPIO_0[11],Location,PIN_B18,Yes ++,GPIO_0[12],Location,PIN_A19,Yes ++,GPIO_0[13],Location,PIN_B19,Yes ++,GPIO_0[14],Location,PIN_A20,Yes ++,GPIO_0[15],Location,PIN_B20,Yes ++,GPIO_0[16],Location,PIN_C21,Yes ++,GPIO_0[17],Location,PIN_C22,Yes ++,GPIO_0[18],Location,PIN_D21,Yes ++,GPIO_0[19],Location,PIN_D22,Yes ++,GPIO_0[20],Location,PIN_E21,Yes ++,GPIO_0[21],Location,PIN_E22,Yes ++,GPIO_0[22],Location,PIN_F21,Yes ++,GPIO_0[23],Location,PIN_F22,Yes ++,GPIO_0[24],Location,PIN_G21,Yes ++,GPIO_0[25],Location,PIN_G22,Yes ++,GPIO_0[26],Location,PIN_J21,Yes ++,GPIO_0[27],Location,PIN_J22,Yes ++,GPIO_0[28],Location,PIN_K21,Yes ++,GPIO_0[29],Location,PIN_K22,Yes ++,GPIO_0[30],Location,PIN_J19,Yes ++,GPIO_0[31],Location,PIN_J20,Yes ++,GPIO_0[32],Location,PIN_J18,Yes ++,GPIO_0[33],Location,PIN_K20,Yes ++,GPIO_0[34],Location,PIN_L19,Yes ++,GPIO_0[35],Location,PIN_L18,Yes ++,GPIO_1[0],Location,PIN_H12,Yes ++,GPIO_1[1],Location,PIN_H13,Yes ++,GPIO_1[2],Location,PIN_H14,Yes ++,GPIO_1[3],Location,PIN_G15,Yes ++,GPIO_1[4],Location,PIN_E14,Yes ++,GPIO_1[5],Location,PIN_E15,Yes ++,GPIO_1[6],Location,PIN_F15,Yes ++,GPIO_1[7],Location,PIN_G16,Yes ++,GPIO_1[8],Location,PIN_F12,Yes ++,GPIO_1[9],Location,PIN_F13,Yes ++,GPIO_1[10],Location,PIN_C14,Yes ++,GPIO_1[11],Location,PIN_D14,Yes ++,GPIO_1[12],Location,PIN_D15,Yes ++,GPIO_1[13],Location,PIN_D16,Yes ++,GPIO_1[14],Location,PIN_C17,Yes ++,GPIO_1[15],Location,PIN_C18,Yes ++,GPIO_1[16],Location,PIN_C19,Yes ++,GPIO_1[17],Location,PIN_C20,Yes ++,GPIO_1[18],Location,PIN_D19,Yes ++,GPIO_1[19],Location,PIN_D20,Yes ++,GPIO_1[20],Location,PIN_E20,Yes ++,GPIO_1[21],Location,PIN_F20,Yes ++,GPIO_1[22],Location,PIN_E19,Yes ++,GPIO_1[23],Location,PIN_E18,Yes ++,GPIO_1[24],Location,PIN_G20,Yes ++,GPIO_1[25],Location,PIN_G18,Yes ++,GPIO_1[26],Location,PIN_G17,Yes ++,GPIO_1[27],Location,PIN_H17,Yes ++,GPIO_1[28],Location,PIN_J15,Yes ++,GPIO_1[29],Location,PIN_H18,Yes ++,GPIO_1[30],Location,PIN_N22,Yes ++,GPIO_1[31],Location,PIN_N21,Yes ++,GPIO_1[32],Location,PIN_P15,Yes ++,GPIO_1[33],Location,PIN_N15,Yes ++,GPIO_1[34],Location,PIN_P17,Yes ++,GPIO_1[35],Location,PIN_P18,Yes ++,GPIO_0[0],I/O Standard,LVTTL,Yes ++,GPIO_0[1],I/O Standard,LVTTL,Yes ++,GPIO_0[2],I/O Standard,LVTTL,Yes ++,GPIO_0[3],I/O Standard,LVTTL,Yes ++,GPIO_0[4],I/O Standard,LVTTL,Yes ++,GPIO_0[5],I/O Standard,LVTTL,Yes ++,GPIO_0[6],I/O Standard,LVTTL,Yes ++,GPIO_0[7],I/O Standard,LVTTL,Yes ++,GPIO_0[8],I/O Standard,LVTTL,Yes ++,GPIO_0[9],I/O Standard,LVTTL,Yes ++,GPIO_0[10],I/O Standard,LVTTL,Yes ++,GPIO_0[11],I/O Standard,LVTTL,Yes ++,GPIO_0[12],I/O Standard,LVTTL,Yes ++,GPIO_0[13],I/O Standard,LVTTL,Yes ++,GPIO_0[14],I/O Standard,LVTTL,Yes ++,GPIO_0[15],I/O Standard,LVTTL,Yes ++,GPIO_0[16],I/O Standard,LVTTL,Yes ++,GPIO_0[17],I/O Standard,LVTTL,Yes ++,GPIO_0[18],I/O Standard,LVTTL,Yes ++,GPIO_0[19],I/O Standard,LVTTL,Yes ++,GPIO_0[20],I/O Standard,LVTTL,Yes ++,GPIO_0[21],I/O Standard,LVTTL,Yes ++,GPIO_0[22],I/O Standard,LVTTL,Yes ++,GPIO_0[23],I/O Standard,LVTTL,Yes ++,GPIO_0[24],I/O Standard,LVTTL,Yes ++,GPIO_0[25],I/O Standard,LVTTL,Yes ++,GPIO_0[26],I/O Standard,LVTTL,Yes ++,GPIO_0[27],I/O Standard,LVTTL,Yes ++,GPIO_0[28],I/O Standard,LVTTL,Yes ++,GPIO_0[29],I/O Standard,LVTTL,Yes ++,GPIO_0[30],I/O Standard,LVTTL,Yes ++,GPIO_0[31],I/O Standard,LVTTL,Yes ++,GPIO_0[32],I/O Standard,LVTTL,Yes ++,GPIO_0[33],I/O Standard,LVTTL,Yes ++,GPIO_0[34],I/O Standard,LVTTL,Yes ++,GPIO_0[35],I/O Standard,LVTTL,Yes ++,GPIO_1[0],I/O Standard,LVTTL,Yes ++,GPIO_1[1],I/O Standard,LVTTL,Yes ++,GPIO_1[2],I/O Standard,LVTTL,Yes ++,GPIO_1[3],I/O Standard,LVTTL,Yes ++,GPIO_1[4],I/O Standard,LVTTL,Yes ++,GPIO_1[5],I/O Standard,LVTTL,Yes ++,GPIO_1[6],I/O Standard,LVTTL,Yes ++,GPIO_1[7],I/O Standard,LVTTL,Yes ++,GPIO_1[8],I/O Standard,LVTTL,Yes ++,GPIO_1[9],I/O Standard,LVTTL,Yes ++,GPIO_1[10],I/O Standard,LVTTL,Yes ++,GPIO_1[11],I/O Standard,LVTTL,Yes ++,GPIO_1[12],I/O Standard,LVTTL,Yes ++,GPIO_1[13],I/O Standard,LVTTL,Yes ++,GPIO_1[14],I/O Standard,LVTTL,Yes ++,GPIO_1[15],I/O Standard,LVTTL,Yes ++,GPIO_1[16],I/O Standard,LVTTL,Yes ++,GPIO_1[17],I/O Standard,LVTTL,Yes ++,GPIO_1[18],I/O Standard,LVTTL,Yes ++,GPIO_1[19],I/O Standard,LVTTL,Yes ++,GPIO_1[20],I/O Standard,LVTTL,Yes ++,GPIO_1[21],I/O Standard,LVTTL,Yes ++,GPIO_1[22],I/O Standard,LVTTL,Yes ++,GPIO_1[23],I/O Standard,LVTTL,Yes ++,GPIO_1[24],I/O Standard,LVTTL,Yes ++,GPIO_1[25],I/O Standard,LVTTL,Yes ++,GPIO_1[26],I/O Standard,LVTTL,Yes ++,GPIO_1[27],I/O Standard,LVTTL,Yes ++,GPIO_1[28],I/O Standard,LVTTL,Yes ++,GPIO_1[29],I/O Standard,LVTTL,Yes ++,GPIO_1[30],I/O Standard,LVTTL,Yes ++,GPIO_1[31],I/O Standard,LVTTL,Yes ++,GPIO_1[32],I/O Standard,LVTTL,Yes ++,GPIO_1[33],I/O Standard,LVTTL,Yes ++,GPIO_1[34],I/O Standard,LVTTL,Yes ++,GPIO_1[35],I/O Standard,LVTTL,Yes ++,SW[0],Location,PIN_L22,Yes ++,SW[1],Location,PIN_L21,Yes ++,SW[2],Location,PIN_M22,Yes ++,SW[3],Location,PIN_V12,Yes ++,SW[4],Location,PIN_W12,Yes ++,SW[5],Location,PIN_U12,Yes ++,SW[6],Location,PIN_U11,Yes ++,SW[7],Location,PIN_M2,Yes ++,SW[8],Location,PIN_M1,Yes ++,SW[9],Location,PIN_L2,Yes ++,SW[0],I/O Standard,LVTTL,Yes ++,SW[1],I/O Standard,LVTTL,Yes ++,SW[2],I/O Standard,LVTTL,Yes ++,SW[3],I/O Standard,LVTTL,Yes ++,SW[4],I/O Standard,LVTTL,Yes ++,SW[5],I/O Standard,LVTTL,Yes ++,SW[6],I/O Standard,LVTTL,Yes ++,SW[7],I/O Standard,LVTTL,Yes ++,SW[8],I/O Standard,LVTTL,Yes ++,SW[9],I/O Standard,LVTTL,Yes ++,HEX0[0],Location,PIN_J2,Yes ++,HEX0[1],Location,PIN_J1,Yes ++,HEX0[2],Location,PIN_H2,Yes ++,HEX0[3],Location,PIN_H1,Yes ++,HEX0[4],Location,PIN_F2,Yes ++,HEX0[5],Location,PIN_F1,Yes ++,HEX0[6],Location,PIN_E2,Yes ++,HEX1[0],Location,PIN_E1,Yes ++,HEX1[1],Location,PIN_H6,Yes ++,HEX1[2],Location,PIN_H5,Yes ++,HEX1[3],Location,PIN_H4,Yes ++,HEX1[4],Location,PIN_G3,Yes ++,HEX1[5],Location,PIN_D2,Yes ++,HEX1[6],Location,PIN_D1,Yes ++,HEX2[0],Location,PIN_G5,Yes ++,HEX2[1],Location,PIN_G6,Yes ++,HEX2[2],Location,PIN_C2,Yes ++,HEX2[3],Location,PIN_C1,Yes ++,HEX2[4],Location,PIN_E3,Yes ++,HEX2[5],Location,PIN_E4,Yes ++,HEX2[6],Location,PIN_D3,Yes ++,HEX3[0],Location,PIN_F4,Yes ++,HEX3[1],Location,PIN_D5,Yes ++,HEX3[2],Location,PIN_D6,Yes ++,HEX3[3],Location,PIN_J4,Yes ++,HEX3[4],Location,PIN_L8,Yes ++,HEX3[5],Location,PIN_F3,Yes ++,HEX3[6],Location,PIN_D4,Yes ++,HEX0[0],I/O Standard,LVTTL,Yes ++,HEX0[1],I/O Standard,LVTTL,Yes ++,HEX0[2],I/O Standard,LVTTL,Yes ++,HEX0[3],I/O Standard,LVTTL,Yes ++,HEX0[4],I/O Standard,LVTTL,Yes ++,HEX0[5],I/O Standard,LVTTL,Yes ++,HEX0[6],I/O Standard,LVTTL,Yes ++,HEX1[0],I/O Standard,LVTTL,Yes ++,HEX1[1],I/O Standard,LVTTL,Yes ++,HEX1[2],I/O Standard,LVTTL,Yes ++,HEX1[3],I/O Standard,LVTTL,Yes ++,HEX1[4],I/O Standard,LVTTL,Yes ++,HEX1[5],I/O Standard,LVTTL,Yes ++,HEX1[6],I/O Standard,LVTTL,Yes ++,HEX2[0],I/O Standard,LVTTL,Yes ++,HEX2[1],I/O Standard,LVTTL,Yes ++,HEX2[2],I/O Standard,LVTTL,Yes ++,HEX2[3],I/O Standard,LVTTL,Yes ++,HEX2[4],I/O Standard,LVTTL,Yes ++,HEX2[5],I/O Standard,LVTTL,Yes ++,HEX2[6],I/O Standard,LVTTL,Yes ++,HEX3[0],I/O Standard,LVTTL,Yes ++,HEX3[1],I/O Standard,LVTTL,Yes ++,HEX3[2],I/O Standard,LVTTL,Yes ++,HEX3[3],I/O Standard,LVTTL,Yes ++,HEX3[4],I/O Standard,LVTTL,Yes ++,HEX3[5],I/O Standard,LVTTL,Yes ++,HEX3[6],I/O Standard,LVTTL,Yes ++,KEY[0],Location,PIN_R22,Yes ++,KEY[1],Location,PIN_R21,Yes ++,KEY[2],Location,PIN_T22,Yes ++,KEY[3],Location,PIN_T21,Yes ++,LEDR[0],Location,PIN_R20,Yes ++,LEDR[1],Location,PIN_R19,Yes ++,LEDR[2],Location,PIN_U19,Yes ++,LEDR[3],Location,PIN_Y19,Yes ++,LEDR[4],Location,PIN_T18,Yes ++,LEDR[5],Location,PIN_V19,Yes ++,LEDR[6],Location,PIN_Y18,Yes ++,LEDR[7],Location,PIN_U18,Yes ++,LEDR[8],Location,PIN_R18,Yes ++,LEDR[9],Location,PIN_R17,Yes ++,LEDG[0],Location,PIN_U22,Yes ++,LEDG[1],Location,PIN_U21,Yes ++,LEDG[2],Location,PIN_V22,Yes ++,LEDG[3],Location,PIN_V21,Yes ++,LEDG[4],Location,PIN_W22,Yes ++,LEDG[5],Location,PIN_W21,Yes ++,LEDG[6],Location,PIN_Y22,Yes ++,LEDG[7],Location,PIN_Y21,Yes ++,KEY[0],I/O Standard,LVTTL,Yes ++,KEY[1],I/O Standard,LVTTL,Yes ++,KEY[2],I/O Standard,LVTTL,Yes ++,KEY[3],I/O Standard,LVTTL,Yes ++,LEDR[0],I/O Standard,LVTTL,Yes ++,LEDR[1],I/O Standard,LVTTL,Yes ++,LEDR[2],I/O Standard,LVTTL,Yes ++,LEDR[3],I/O Standard,LVTTL,Yes ++,LEDR[4],I/O Standard,LVTTL,Yes ++,LEDR[5],I/O Standard,LVTTL,Yes ++,LEDR[6],I/O Standard,LVTTL,Yes ++,LEDR[7],I/O Standard,LVTTL,Yes ++,LEDR[8],I/O Standard,LVTTL,Yes ++,LEDR[9],I/O Standard,LVTTL,Yes ++,LEDG[0],I/O Standard,LVTTL,Yes ++,LEDG[1],I/O Standard,LVTTL,Yes ++,LEDG[2],I/O Standard,LVTTL,Yes ++,LEDG[3],I/O Standard,LVTTL,Yes ++,LEDG[4],I/O Standard,LVTTL,Yes ++,LEDG[5],I/O Standard,LVTTL,Yes ++,LEDG[6],I/O Standard,LVTTL,Yes ++,LEDG[7],I/O Standard,LVTTL,Yes ++,CLOCK_27[0],Location,PIN_D12,Yes ++,CLOCK_27[1],Location,PIN_E12,Yes ++,CLOCK_24[0],Location,PIN_B12,Yes ++,CLOCK_24[1],Location,PIN_A12,Yes ++,CLOCK_50,Location,PIN_L1,Yes ++,EXT_CLOCK,Location,PIN_M21,Yes ++,CLOCK_27[1],I/O Standard,LVTTL,Yes ++,CLOCK_24[0],I/O Standard,LVTTL,Yes ++,CLOCK_24[1],I/O Standard,LVTTL,Yes ++,CLOCK_50,I/O Standard,LVTTL,Yes ++,EXT_CLOCK,I/O Standard,LVTTL,Yes ++,PS2_CLK,Location,PIN_H15,Yes ++,PS2_DAT,Location,PIN_J14,Yes ++,UART_RXD,Location,PIN_F14,Yes ++,UART_TXD,Location,PIN_G12,Yes ++,PS2_CLK,I/O Standard,LVTTL,Yes ++,PS2_DAT,I/O Standard,LVTTL,Yes ++,UART_RXD,I/O Standard,LVTTL,Yes ++,UART_TXD,I/O Standard,LVTTL,Yes ++,TDI,Location,PIN_E8,Yes ++,TCS,Location,PIN_D8,Yes ++,TCK,Location,PIN_C7,Yes ++,TDO,Location,PIN_D7,Yes ++,TDI,I/O Standard,LVTTL,Yes ++,TCS,I/O Standard,LVTTL,Yes ++,TCK,I/O Standard,LVTTL,Yes ++,TDO,I/O Standard,LVTTL,Yes ++,VGA_R[0],Location,PIN_D9,Yes ++,VGA_R[1],Location,PIN_C9,Yes ++,VGA_R[2],Location,PIN_A7,Yes ++,VGA_R[3],Location,PIN_B7,Yes ++,VGA_G[0],Location,PIN_B8,Yes ++,VGA_G[1],Location,PIN_C10,Yes ++,VGA_G[2],Location,PIN_B9,Yes ++,VGA_G[3],Location,PIN_A8,Yes ++,VGA_B[0],Location,PIN_A9,Yes ++,VGA_B[1],Location,PIN_D11,Yes ++,VGA_B[2],Location,PIN_A10,Yes ++,VGA_B[3],Location,PIN_B10,Yes ++,VGA_HS,Location,PIN_A11,Yes ++,VGA_VS,Location,PIN_B11,Yes ++,VGA_R[0],I/O Standard,LVTTL,Yes ++,VGA_R[1],I/O Standard,LVTTL,Yes ++,VGA_R[2],I/O Standard,LVTTL,Yes ++,VGA_R[3],I/O Standard,LVTTL,Yes ++,VGA_G[0],I/O Standard,LVTTL,Yes ++,VGA_G[1],I/O Standard,LVTTL,Yes ++,VGA_G[2],I/O Standard,LVTTL,Yes ++,VGA_G[3],I/O Standard,LVTTL,Yes ++,VGA_B[0],I/O Standard,LVTTL,Yes ++,VGA_B[1],I/O Standard,LVTTL,Yes ++,VGA_B[2],I/O Standard,LVTTL,Yes ++,VGA_B[3],I/O Standard,LVTTL,Yes ++,VGA_HS,I/O Standard,LVTTL,Yes ++,VGA_VS,I/O Standard,LVTTL,Yes ++,I2C_SCLK,Location,PIN_A3,Yes ++,I2C_SDAT,Location,PIN_B3,Yes ++,AUD_ADCLRCK,Location,PIN_A6,Yes ++,AUD_ADCDAT,Location,PIN_B6,Yes ++,AUD_DACLRCK,Location,PIN_A5,Yes ++,AUD_DACDAT,Location,PIN_B5,Yes ++,AUD_XCK,Location,PIN_B4,Yes ++,AUD_BCLK,Location,PIN_A4,Yes ++,I2C_SCLK,I/O Standard,LVTTL,Yes ++,I2C_SDAT,I/O Standard,LVTTL,Yes ++,AUD_ADCLRCK,I/O Standard,LVTTL,Yes ++,AUD_ADCDAT,I/O Standard,LVTTL,Yes ++,AUD_DACLRCK,I/O Standard,LVTTL,Yes ++,AUD_DACDAT,I/O Standard,LVTTL,Yes ++,AUD_XCK,I/O Standard,LVTTL,Yes ++,AUD_BCLK,I/O Standard,LVTTL,Yes ++,DRAM_ADDR[0],Location,PIN_W4,Yes ++,DRAM_ADDR[1],Location,PIN_W5,Yes ++,DRAM_ADDR[2],Location,PIN_Y3,Yes ++,DRAM_ADDR[3],Location,PIN_Y4,Yes ++,DRAM_ADDR[4],Location,PIN_R6,Yes ++,DRAM_ADDR[5],Location,PIN_R5,Yes ++,DRAM_ADDR[6],Location,PIN_P6,Yes ++,DRAM_ADDR[7],Location,PIN_P5,Yes ++,DRAM_ADDR[8],Location,PIN_P3,Yes ++,DRAM_ADDR[9],Location,PIN_N4,Yes ++,DRAM_ADDR[10],Location,PIN_W3,Yes ++,DRAM_ADDR[11],Location,PIN_N6,Yes ++,DRAM_BA_0,Location,PIN_U3,Yes ++,DRAM_BA_1,Location,PIN_V4,Yes ++,DRAM_CAS_N,Location,PIN_T3,Yes ++,DRAM_CKE,Location,PIN_N3,Yes ++,DRAM_CLK,Location,PIN_U4,Yes ++,DRAM_CS_N,Location,PIN_T6,Yes ++,DRAM_DQ[0],Location,PIN_U1,Yes ++,DRAM_DQ[1],Location,PIN_U2,Yes ++,DRAM_DQ[2],Location,PIN_V1,Yes ++,DRAM_DQ[3],Location,PIN_V2,Yes ++,DRAM_DQ[4],Location,PIN_W1,Yes ++,DRAM_DQ[5],Location,PIN_W2,Yes ++,DRAM_DQ[6],Location,PIN_Y1,Yes ++,DRAM_DQ[7],Location,PIN_Y2,Yes ++,DRAM_DQ[8],Location,PIN_N1,Yes ++,DRAM_DQ[9],Location,PIN_N2,Yes ++,DRAM_DQ[10],Location,PIN_P1,Yes ++,DRAM_DQ[11],Location,PIN_P2,Yes ++,DRAM_DQ[12],Location,PIN_R1,Yes ++,DRAM_DQ[13],Location,PIN_R2,Yes ++,DRAM_DQ[14],Location,PIN_T1,Yes ++,DRAM_DQ[15],Location,PIN_T2,Yes ++,DRAM_LDQM,Location,PIN_R7,Yes ++,DRAM_RAS_N,Location,PIN_T5,Yes ++,DRAM_UDQM,Location,PIN_M5,Yes ++,DRAM_WE_N,Location,PIN_R8,Yes ++,FL_ADDR[0],Location,PIN_AB20,Yes ++,FL_ADDR[1],Location,PIN_AA14,Yes ++,FL_ADDR[2],Location,PIN_Y16,Yes ++,FL_ADDR[3],Location,PIN_R15,Yes ++,FL_ADDR[4],Location,PIN_T15,Yes ++,FL_ADDR[5],Location,PIN_U15,Yes ++,FL_ADDR[6],Location,PIN_V15,Yes ++,FL_ADDR[7],Location,PIN_W15,Yes ++,FL_ADDR[8],Location,PIN_R14,Yes ++,FL_ADDR[9],Location,PIN_Y13,Yes ++,FL_ADDR[10],Location,PIN_R12,Yes ++,FL_ADDR[11],Location,PIN_T12,Yes ++,FL_ADDR[12],Location,PIN_AB14,Yes ++,FL_ADDR[13],Location,PIN_AA13,Yes ++,FL_ADDR[14],Location,PIN_AB13,Yes ++,FL_ADDR[15],Location,PIN_AA12,Yes ++,FL_ADDR[16],Location,PIN_AB12,Yes ++,FL_ADDR[17],Location,PIN_AA20,Yes ++,FL_ADDR[18],Location,PIN_U14,Yes ++,FL_ADDR[19],Location,PIN_V14,Yes ++,FL_ADDR[20],Location,PIN_U13,Yes ++,FL_ADDR[21],Location,PIN_R13,Yes ++,FL_DQ[0],Location,PIN_AB16,Yes ++,FL_DQ[1],Location,PIN_AA16,Yes ++,FL_DQ[2],Location,PIN_AB17,Yes ++,FL_DQ[3],Location,PIN_AA17,Yes ++,FL_DQ[4],Location,PIN_AB18,Yes ++,FL_DQ[5],Location,PIN_AA18,Yes ++,FL_DQ[6],Location,PIN_AB19,Yes ++,FL_DQ[7],Location,PIN_AA19,Yes ++,FL_OE_N,Location,PIN_AA15,Yes ++,FL_RST_N,Location,PIN_W14,Yes ++,FL_WE_N,Location,PIN_Y14,Yes ++,FL_CE_N,Location,PIN_AB15,Yes ++,SRAM_ADDR[0],Location,PIN_AA3,Yes ++,SRAM_ADDR[1],Location,PIN_AB3,Yes ++,SRAM_ADDR[2],Location,PIN_AA4,Yes ++,SRAM_ADDR[3],Location,PIN_AB4,Yes ++,SRAM_ADDR[4],Location,PIN_AA5,Yes ++,SRAM_ADDR[5],Location,PIN_AB10,Yes ++,SRAM_ADDR[6],Location,PIN_AA11,Yes ++,SRAM_ADDR[7],Location,PIN_AB11,Yes ++,SRAM_ADDR[8],Location,PIN_V11,Yes ++,SRAM_ADDR[9],Location,PIN_W11,Yes ++,SRAM_ADDR[10],Location,PIN_R11,Yes ++,SRAM_ADDR[11],Location,PIN_T11,Yes ++,SRAM_ADDR[12],Location,PIN_Y10,Yes ++,SRAM_ADDR[13],Location,PIN_U10,Yes ++,SRAM_ADDR[14],Location,PIN_R10,Yes ++,SRAM_ADDR[15],Location,PIN_T7,Yes ++,SRAM_ADDR[16],Location,PIN_Y6,Yes ++,SRAM_ADDR[17],Location,PIN_Y5,Yes ++,SRAM_CE_N,Location,PIN_AB5,Yes ++,SRAM_DQ[0],Location,PIN_AA6,Yes ++,SRAM_DQ[1],Location,PIN_AB6,Yes ++,SRAM_DQ[2],Location,PIN_AA7,Yes ++,SRAM_DQ[3],Location,PIN_AB7,Yes ++,SRAM_DQ[4],Location,PIN_AA8,Yes ++,SRAM_DQ[5],Location,PIN_AB8,Yes ++,SRAM_DQ[6],Location,PIN_AA9,Yes ++,SRAM_DQ[7],Location,PIN_AB9,Yes ++,SRAM_DQ[8],Location,PIN_Y9,Yes ++,SRAM_DQ[9],Location,PIN_W9,Yes ++,SRAM_DQ[10],Location,PIN_V9,Yes ++,SRAM_DQ[11],Location,PIN_U9,Yes ++,SRAM_DQ[12],Location,PIN_R9,Yes ++,SRAM_DQ[13],Location,PIN_W8,Yes ++,SRAM_DQ[14],Location,PIN_V8,Yes ++,SRAM_DQ[15],Location,PIN_U8,Yes ++,SRAM_LB_N,Location,PIN_Y7,Yes ++,SRAM_OE_N,Location,PIN_T8,Yes ++,SRAM_UB_N,Location,PIN_W7,Yes ++,SRAM_WE_N,Location,PIN_AA10,Yes ++,SD_nCS,Location,PIN_U20,Yes ++,SD_MOSI,Location,PIN_Y20,Yes ++,SD_SCLK,Location,PIN_V20,Yes ++,SD_MISO,Location,PIN_W20,Yes ++ +diff --git a/T65/T65.vhd b/T65/T65.vhd +index 4a21d79..09253fe 100644 +--- a/T65/T65.vhd ++++ b/T65/T65.vhd +@@ -1,564 +1,564 @@ +--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 301 more merging
+--- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- 65C02 and 65C816 modes are incomplete
+--- Undocumented instructions are not supported
+--- Some interface signals behaves incorrect
+---
+--- File history :
+---
+--- 0246 : First release
+---
+-
+-library IEEE;
+- use IEEE.std_logic_1164.all;
+- use IEEE.numeric_std.all;
+- use work.T65_Pack.all;
+-
+--- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
+--- the ready signal to limit the CPU.
+-entity T65 is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Res_n : in std_logic;
+- Enable : in std_logic;
+- Clk : in std_logic;
+- Rdy : in std_logic;
+- Abort_n : in std_logic;
+- IRQ_n : in std_logic;
+- NMI_n : in std_logic;
+- SO_n : in std_logic;
+- R_W_n : out std_logic;
+- Sync : out std_logic;
+- EF : out std_logic;
+- MF : out std_logic;
+- XF : out std_logic;
+- ML_n : out std_logic;
+- VP_n : out std_logic;
+- VDA : out std_logic;
+- VPA : out std_logic;
+- A : out std_logic_vector(23 downto 0);
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0)
+- );
+-end T65;
+-
+-architecture rtl of T65 is
+-
+- -- Registers
+- signal ABC, X, Y, D : std_logic_vector(15 downto 0);
+- signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
+- signal BAH : std_logic_vector(7 downto 0);
+- signal BAL : std_logic_vector(8 downto 0);
+- signal PBR : std_logic_vector(7 downto 0);
+- signal DBR : std_logic_vector(7 downto 0);
+- signal PC : unsigned(15 downto 0);
+- signal S : unsigned(15 downto 0);
+- signal EF_i : std_logic;
+- signal MF_i : std_logic;
+- signal XF_i : std_logic;
+-
+- signal IR : std_logic_vector(7 downto 0);
+- signal MCycle : std_logic_vector(2 downto 0);
+-
+- signal Mode_r : std_logic_vector(1 downto 0);
+- signal ALU_Op_r : std_logic_vector(3 downto 0);
+- signal Write_Data_r : std_logic_vector(2 downto 0);
+- signal Set_Addr_To_r : std_logic_vector(1 downto 0);
+- signal PCAdder : unsigned(8 downto 0);
+-
+- signal RstCycle : std_logic;
+- signal IRQCycle : std_logic;
+- signal NMICycle : std_logic;
+-
+- signal B_o : std_logic;
+- signal SO_n_o : std_logic;
+- signal IRQ_n_o : std_logic;
+- signal NMI_n_o : std_logic;
+- signal NMIAct : std_logic;
+-
+- signal Break : std_logic;
+-
+- -- ALU signals
+- signal BusA : std_logic_vector(7 downto 0);
+- signal BusA_r : std_logic_vector(7 downto 0);
+- signal BusB : std_logic_vector(7 downto 0);
+- signal ALU_Q : std_logic_vector(7 downto 0);
+- signal P_Out : std_logic_vector(7 downto 0);
+-
+- -- Micro code outputs
+- signal LCycle : std_logic_vector(2 downto 0);
+- signal ALU_Op : std_logic_vector(3 downto 0);
+- signal Set_BusA_To : std_logic_vector(2 downto 0);
+- signal Set_Addr_To : std_logic_vector(1 downto 0);
+- signal Write_Data : std_logic_vector(2 downto 0);
+- signal Jump : std_logic_vector(1 downto 0);
+- signal BAAdd : std_logic_vector(1 downto 0);
+- signal BreakAtNA : std_logic;
+- signal ADAdd : std_logic;
+- signal AddY : std_logic;
+- signal PCAdd : std_logic;
+- signal Inc_S : std_logic;
+- signal Dec_S : std_logic;
+- signal LDA : std_logic;
+- signal LDP : std_logic;
+- signal LDX : std_logic;
+- signal LDY : std_logic;
+- signal LDS : std_logic;
+- signal LDDI : std_logic;
+- signal LDALU : std_logic;
+- signal LDAD : std_logic;
+- signal LDBAL : std_logic;
+- signal LDBAH : std_logic;
+- signal SaveP : std_logic;
+- signal Write : std_logic;
+-
+- signal really_rdy : std_logic;
+- signal R_W_n_i : std_logic;
+-
+-begin
+- -- ehenciak : gate Rdy with read/write to make an "OK, it's
+- -- really OK to stop the processor now if Rdy is
+- -- deasserted" signal
+- really_rdy <= Rdy or not(R_W_n_i);
+-
+- -- ehenciak : Drive R_W_n_i off chip.
+- R_W_n <= R_W_n_i;
+-
+- Sync <= '1' when MCycle = "000" else '0';
+- EF <= EF_i;
+- MF <= MF_i;
+- XF <= XF_i;
+- ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
+- VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
+- VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!!
+- VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
+-
+- mcode : T65_MCode
+- port map(
+- Mode => Mode_r,
+- IR => IR,
+- MCycle => MCycle,
+- P => P,
+- LCycle => LCycle,
+- ALU_Op => ALU_Op,
+- Set_BusA_To => Set_BusA_To,
+- Set_Addr_To => Set_Addr_To,
+- Write_Data => Write_Data,
+- Jump => Jump,
+- BAAdd => BAAdd,
+- BreakAtNA => BreakAtNA,
+- ADAdd => ADAdd,
+- AddY => AddY,
+- PCAdd => PCAdd,
+- Inc_S => Inc_S,
+- Dec_S => Dec_S,
+- LDA => LDA,
+- LDP => LDP,
+- LDX => LDX,
+- LDY => LDY,
+- LDS => LDS,
+- LDDI => LDDI,
+- LDALU => LDALU,
+- LDAD => LDAD,
+- LDBAL => LDBAL,
+- LDBAH => LDBAH,
+- SaveP => SaveP,
+- Write => Write
+- );
+-
+- alu : T65_ALU
+- port map(
+- Mode => Mode_r,
+- Op => ALU_Op_r,
+- BusA => BusA_r,
+- BusB => BusB,
+- P_In => P,
+- P_Out => P_Out,
+- Q => ALU_Q
+- );
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- PC <= (others => '0'); -- Program Counter
+- IR <= "00000000";
+- S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
+- D <= (others => '0');
+- PBR <= (others => '0');
+- DBR <= (others => '0');
+-
+- Mode_r <= (others => '0');
+- ALU_Op_r <= "1100";
+- Write_Data_r <= "000";
+- Set_Addr_To_r <= "00";
+-
+- R_W_n_i <= '1';
+- EF_i <= '1';
+- MF_i <= '1';
+- XF_i <= '1';
+-
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- R_W_n_i <= not Write or RstCycle;
+-
+- D <= (others => '1'); -- Dummy
+- PBR <= (others => '1'); -- Dummy
+- DBR <= (others => '1'); -- Dummy
+- EF_i <= '0'; -- Dummy
+- MF_i <= '0'; -- Dummy
+- XF_i <= '0'; -- Dummy
+-
+- if MCycle = "000" then
+- Mode_r <= Mode;
+-
+- if IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+-
+- if IRQCycle = '1' or NMICycle = '1' then
+- IR <= "00000000";
+- else
+- IR <= DI;
+- end if;
+- end if;
+-
+- ALU_Op_r <= ALU_Op;
+- Write_Data_r <= Write_Data;
+- if Break = '1' then
+- Set_Addr_To_r <= "00";
+- else
+- Set_Addr_To_r <= Set_Addr_To;
+- end if;
+-
+- if Inc_S = '1' then
+- S <= S + 1;
+- end if;
+- if Dec_S = '1' and RstCycle = '0' then
+- S <= S - 1;
+- end if;
+- if LDS = '1' then
+- S(7 downto 0) <= unsigned(ALU_Q);
+- end if;
+-
+- if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+- --
+- -- jump control logic
+- --
+- case Jump is
+- when "01" =>
+- PC <= PC + 1;
+-
+- when "10" =>
+- PC <= unsigned(DI & DL);
+-
+- when "11" =>
+- if PCAdder(8) = '1' then
+- if DL(7) = '0' then
+- PC(15 downto 8) <= PC(15 downto 8) + 1;
+- else
+- PC(15 downto 8) <= PC(15 downto 8) - 1;
+- end if;
+- end if;
+- PC(7 downto 0) <= PCAdder(7 downto 0);
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
+- else "0" & PC(7 downto 0);
+-
+- process (Clk)
+- begin
+- if Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = "000" then
+- if LDA = '1' then
+- ABC(7 downto 0) <= ALU_Q;
+- end if;
+- if LDX = '1' then
+- X(7 downto 0) <= ALU_Q;
+- end if;
+- if LDY = '1' then
+- Y(7 downto 0) <= ALU_Q;
+- end if;
+- if (LDA or LDX or LDY) = '1' then
+- P <= P_Out;
+- end if;
+- end if;
+- if SaveP = '1' then
+- P <= P_Out;
+- end if;
+- if LDP = '1' then
+- P <= ALU_Q;
+- end if;
+- if IR(4 downto 0) = "11000" then
+- case IR(7 downto 5) is
+- when "000" =>
+- P(Flag_C) <= '0';
+- when "001" =>
+- P(Flag_C) <= '1';
+- when "010" =>
+- P(Flag_I) <= '0';
+- when "011" =>
+- P(Flag_I) <= '1';
+- when "101" =>
+- P(Flag_V) <= '0';
+- when "110" =>
+- P(Flag_D) <= '0';
+- when "111" =>
+- P(Flag_D) <= '1';
+- when others =>
+- end case;
+- end if;
+-
+- --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
+- -- P(Flag_B) <= '1';
+- --end if;
+- --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- -- P(Flag_I) <= '1';
+- -- P(Flag_B) <= B_o;
+- --end if;
+-
+- -- B=1 always on the 6502
+- P(Flag_B) <= '1';
+- if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- if MCycle = "011" then
+- -- B=0 in *copy* of P pushed onto the stack
+- P(Flag_B) <= '0';
+- elsif MCycle = "100" then
+- P(Flag_I) <= '1';
+- end if;
+- end if;
+-
+- if SO_n_o = '1' and SO_n = '0' then
+- P(Flag_V) <= '1';
+- end if;
+- if RstCycle = '1' and Mode_r /= "00" then
+- P(Flag_1) <= '1';
+- P(Flag_D) <= '0';
+- P(Flag_I) <= '1';
+- end if;
+- P(Flag_1) <= '1';
+-
+- B_o <= P(Flag_B);
+- SO_n_o <= SO_n;
+- IRQ_n_o <= IRQ_n;
+- NMI_n_o <= NMI_n;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+----------------------------------------------------------------------------
+---
+--- Buses
+---
+----------------------------------------------------------------------------
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- BusA_r <= (others => '0');
+- BusB <= (others => '0');
+- AD <= (others => '0');
+- BAL <= (others => '0');
+- BAH <= (others => '0');
+- DL <= (others => '0');
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (Rdy = '1') then
+- BusA_r <= BusA;
+- BusB <= DI;
+-
+- case BAAdd is
+- when "01" =>
+- -- BA Inc
+- AD <= std_logic_vector(unsigned(AD) + 1);
+- BAL <= std_logic_vector(unsigned(BAL) + 1);
+- when "10" =>
+- -- BA Add
+- BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
+- when "11" =>
+- -- BA Adj
+- if BAL(8) = '1' then
+- BAH <= std_logic_vector(unsigned(BAH) + 1);
+- end if;
+- when others =>
+- end case;
+-
+- -- ehenciak : modified to use Y register as well (bugfix)
+- if ADAdd = '1' then
+- if (AddY = '1') then
+- AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
+- else
+- AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
+- end if;
+- end if;
+-
+- if IR = "00000000" then
+- BAL <= (others => '1');
+- BAH <= (others => '1');
+- if RstCycle = '1' then
+- BAL(2 downto 0) <= "100";
+- elsif NMICycle = '1' then
+- BAL(2 downto 0) <= "010";
+- else
+- BAL(2 downto 0) <= "110";
+- end if;
+- if Set_addr_To_r = "11" then
+- BAL(0) <= '1';
+- end if;
+- end if;
+-
+-
+- if LDDI = '1' then
+- DL <= DI;
+- end if;
+- if LDALU = '1' then
+- DL <= ALU_Q;
+- end if;
+- if LDAD = '1' then
+- AD <= DI;
+- end if;
+- if LDBAL = '1' then
+- BAL(7 downto 0) <= DI;
+- end if;
+- if LDBAH = '1' then
+- BAH <= DI;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
+-
+-
+- with Set_BusA_To select
+- BusA <= DI when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- (others => '-') when others;
+-
+- with Set_Addr_To_r select
+- A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
+- DBR & "00000000" & AD when "10",
+- "00000000" & BAH & BAL(7 downto 0) when "11",
+- PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
+-
+- with Write_Data_r select
+- DO <= DL when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- std_logic_vector(PC(7 downto 0)) when "110",
+- std_logic_vector(PC(15 downto 8)) when others;
+-
+--------------------------------------------------------------------------
+---
+--- Main state machine
+---
+--------------------------------------------------------------------------
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- MCycle <= "001";
+- RstCycle <= '1';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- NMIAct <= '0';
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = LCycle or Break = '1' then
+- MCycle <= "000";
+- RstCycle <= '0';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- if NMIAct = '1' then
+- NMICycle <= '1';
+- elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
+- IRQCycle <= '1';
+- end if;
+- else
+- MCycle <= std_logic_vector(unsigned(MCycle) + 1);
+- end if;
+-
+- if NMICycle = '1' then
+- NMIAct <= '0';
+- end if;
+- if NMI_n_o = '1' and NMI_n = '0' then
+- NMIAct <= '1';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-end;
++-- **** ++-- T65(b) core. In an effort to merge and maintain bug fixes .... ++-- ++-- ++-- Ver 301 more merging ++-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust* ++-- MikeJ March 2005 ++-- Latest version from www.fpgaarcade.com (original www.opencores.org) ++-- ++-- **** ++-- ++-- 65xx compatible microprocessor core ++-- ++-- Version : 0246 ++-- ++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written permission. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- Please report bugs to the author, but before you do so, please ++-- make sure that this is not a derivative work and that ++-- you have the latest version of this file. ++-- ++-- The latest version of this file can be found at: ++-- http://www.opencores.org/cvsweb.shtml/t65/ ++-- ++-- Limitations : ++-- ++-- 65C02 and 65C816 modes are incomplete ++-- Undocumented instructions are not supported ++-- Some interface signals behaves incorrect ++-- ++-- File history : ++-- ++-- 0246 : First release ++-- ++ ++library IEEE; ++ use IEEE.std_logic_1164.all; ++ use IEEE.numeric_std.all; ++ use work.T65_Pack.all; ++ ++-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use ++-- the ready signal to limit the CPU. ++entity T65 is ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 ++ Res_n : in std_logic; ++ Enable : in std_logic; ++ Clk : in std_logic; ++ Rdy : in std_logic; ++ Abort_n : in std_logic; ++ IRQ_n : in std_logic; ++ NMI_n : in std_logic; ++ SO_n : in std_logic; ++ R_W_n : out std_logic; ++ Sync : out std_logic; ++ EF : out std_logic; ++ MF : out std_logic; ++ XF : out std_logic; ++ ML_n : out std_logic; ++ VP_n : out std_logic; ++ VDA : out std_logic; ++ VPA : out std_logic; ++ A : out std_logic_vector(23 downto 0); ++ DI : in std_logic_vector(7 downto 0); ++ DO : out std_logic_vector(7 downto 0) ++ ); ++end T65; ++ ++architecture rtl of T65 is ++ ++ -- Registers ++ signal ABC, X, Y, D : std_logic_vector(15 downto 0); ++ signal P, AD, DL : std_logic_vector(7 downto 0) := x"00"; ++ signal BAH : std_logic_vector(7 downto 0); ++ signal BAL : std_logic_vector(8 downto 0); ++ signal PBR : std_logic_vector(7 downto 0); ++ signal DBR : std_logic_vector(7 downto 0); ++ signal PC : unsigned(15 downto 0); ++ signal S : unsigned(15 downto 0); ++ signal EF_i : std_logic; ++ signal MF_i : std_logic; ++ signal XF_i : std_logic; ++ ++ signal IR : std_logic_vector(7 downto 0); ++ signal MCycle : std_logic_vector(2 downto 0); ++ ++ signal Mode_r : std_logic_vector(1 downto 0); ++ signal ALU_Op_r : std_logic_vector(3 downto 0); ++ signal Write_Data_r : std_logic_vector(2 downto 0); ++ signal Set_Addr_To_r : std_logic_vector(1 downto 0); ++ signal PCAdder : unsigned(8 downto 0); ++ ++ signal RstCycle : std_logic; ++ signal IRQCycle : std_logic; ++ signal NMICycle : std_logic; ++ ++ signal B_o : std_logic; ++ signal SO_n_o : std_logic; ++ signal IRQ_n_o : std_logic; ++ signal NMI_n_o : std_logic; ++ signal NMIAct : std_logic; ++ ++ signal Break : std_logic; ++ ++ -- ALU signals ++ signal BusA : std_logic_vector(7 downto 0); ++ signal BusA_r : std_logic_vector(7 downto 0); ++ signal BusB : std_logic_vector(7 downto 0); ++ signal ALU_Q : std_logic_vector(7 downto 0); ++ signal P_Out : std_logic_vector(7 downto 0); ++ ++ -- Micro code outputs ++ signal LCycle : std_logic_vector(2 downto 0); ++ signal ALU_Op : std_logic_vector(3 downto 0); ++ signal Set_BusA_To : std_logic_vector(2 downto 0); ++ signal Set_Addr_To : std_logic_vector(1 downto 0); ++ signal Write_Data : std_logic_vector(2 downto 0); ++ signal Jump : std_logic_vector(1 downto 0); ++ signal BAAdd : std_logic_vector(1 downto 0); ++ signal BreakAtNA : std_logic; ++ signal ADAdd : std_logic; ++ signal AddY : std_logic; ++ signal PCAdd : std_logic; ++ signal Inc_S : std_logic; ++ signal Dec_S : std_logic; ++ signal LDA : std_logic; ++ signal LDP : std_logic; ++ signal LDX : std_logic; ++ signal LDY : std_logic; ++ signal LDS : std_logic; ++ signal LDDI : std_logic; ++ signal LDALU : std_logic; ++ signal LDAD : std_logic; ++ signal LDBAL : std_logic; ++ signal LDBAH : std_logic; ++ signal SaveP : std_logic; ++ signal Write : std_logic; ++ ++ signal really_rdy : std_logic; ++ signal R_W_n_i : std_logic; ++ ++begin ++ -- ehenciak : gate Rdy with read/write to make an "OK, it's ++ -- really OK to stop the processor now if Rdy is ++ -- deasserted" signal ++ really_rdy <= Rdy or not(R_W_n_i); ++ ++ -- ehenciak : Drive R_W_n_i off chip. ++ R_W_n <= R_W_n_i; ++ ++ Sync <= '1' when MCycle = "000" else '0'; ++ EF <= EF_i; ++ MF <= MF_i; ++ XF <= XF_i; ++ ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; ++ VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; ++ VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!! ++ VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! ++ ++ mcode : T65_MCode ++ port map( ++ Mode => Mode_r, ++ IR => IR, ++ MCycle => MCycle, ++ P => P, ++ LCycle => LCycle, ++ ALU_Op => ALU_Op, ++ Set_BusA_To => Set_BusA_To, ++ Set_Addr_To => Set_Addr_To, ++ Write_Data => Write_Data, ++ Jump => Jump, ++ BAAdd => BAAdd, ++ BreakAtNA => BreakAtNA, ++ ADAdd => ADAdd, ++ AddY => AddY, ++ PCAdd => PCAdd, ++ Inc_S => Inc_S, ++ Dec_S => Dec_S, ++ LDA => LDA, ++ LDP => LDP, ++ LDX => LDX, ++ LDY => LDY, ++ LDS => LDS, ++ LDDI => LDDI, ++ LDALU => LDALU, ++ LDAD => LDAD, ++ LDBAL => LDBAL, ++ LDBAH => LDBAH, ++ SaveP => SaveP, ++ Write => Write ++ ); ++ ++ alu : T65_ALU ++ port map( ++ Mode => Mode_r, ++ Op => ALU_Op_r, ++ BusA => BusA_r, ++ BusB => BusB, ++ P_In => P, ++ P_Out => P_Out, ++ Q => ALU_Q ++ ); ++ ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ PC <= (others => '0'); -- Program Counter ++ IR <= "00000000"; ++ S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! ++ D <= (others => '0'); ++ PBR <= (others => '0'); ++ DBR <= (others => '0'); ++ ++ Mode_r <= (others => '0'); ++ ALU_Op_r <= "1100"; ++ Write_Data_r <= "000"; ++ Set_Addr_To_r <= "00"; ++ ++ R_W_n_i <= '1'; ++ EF_i <= '1'; ++ MF_i <= '1'; ++ XF_i <= '1'; ++ ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ R_W_n_i <= not Write or RstCycle; ++ ++ D <= (others => '1'); -- Dummy ++ PBR <= (others => '1'); -- Dummy ++ DBR <= (others => '1'); -- Dummy ++ EF_i <= '0'; -- Dummy ++ MF_i <= '0'; -- Dummy ++ XF_i <= '0'; -- Dummy ++ ++ if MCycle = "000" then ++ Mode_r <= Mode; ++ ++ if IRQCycle = '0' and NMICycle = '0' then ++ PC <= PC + 1; ++ end if; ++ ++ if IRQCycle = '1' or NMICycle = '1' then ++ IR <= "00000000"; ++ else ++ IR <= DI; ++ end if; ++ end if; ++ ++ ALU_Op_r <= ALU_Op; ++ Write_Data_r <= Write_Data; ++ if Break = '1' then ++ Set_Addr_To_r <= "00"; ++ else ++ Set_Addr_To_r <= Set_Addr_To; ++ end if; ++ ++ if Inc_S = '1' then ++ S <= S + 1; ++ end if; ++ if Dec_S = '1' and RstCycle = '0' then ++ S <= S - 1; ++ end if; ++ if LDS = '1' then ++ S(7 downto 0) <= unsigned(ALU_Q); ++ end if; ++ ++ if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then ++ PC <= PC + 1; ++ end if; ++ -- ++ -- jump control logic ++ -- ++ case Jump is ++ when "01" => ++ PC <= PC + 1; ++ ++ when "10" => ++ PC <= unsigned(DI & DL); ++ ++ when "11" => ++ if PCAdder(8) = '1' then ++ if DL(7) = '0' then ++ PC(15 downto 8) <= PC(15 downto 8) + 1; ++ else ++ PC(15 downto 8) <= PC(15 downto 8) - 1; ++ end if; ++ end if; ++ PC(7 downto 0) <= PCAdder(7 downto 0); ++ ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' ++ else "0" & PC(7 downto 0); ++ ++ process (Clk) ++ begin ++ if Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ if MCycle = "000" then ++ if LDA = '1' then ++ ABC(7 downto 0) <= ALU_Q; ++ end if; ++ if LDX = '1' then ++ X(7 downto 0) <= ALU_Q; ++ end if; ++ if LDY = '1' then ++ Y(7 downto 0) <= ALU_Q; ++ end if; ++ if (LDA or LDX or LDY) = '1' then ++ P <= P_Out; ++ end if; ++ end if; ++ if SaveP = '1' then ++ P <= P_Out; ++ end if; ++ if LDP = '1' then ++ P <= ALU_Q; ++ end if; ++ if IR(4 downto 0) = "11000" then ++ case IR(7 downto 5) is ++ when "000" => ++ P(Flag_C) <= '0'; ++ when "001" => ++ P(Flag_C) <= '1'; ++ when "010" => ++ P(Flag_I) <= '0'; ++ when "011" => ++ P(Flag_I) <= '1'; ++ when "101" => ++ P(Flag_V) <= '0'; ++ when "110" => ++ P(Flag_D) <= '0'; ++ when "111" => ++ P(Flag_D) <= '1'; ++ when others => ++ end case; ++ end if; ++ ++ --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then ++ -- P(Flag_B) <= '1'; ++ --end if; ++ --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then ++ -- P(Flag_I) <= '1'; ++ -- P(Flag_B) <= B_o; ++ --end if; ++ ++ -- B=1 always on the 6502 ++ P(Flag_B) <= '1'; ++ if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then ++ if MCycle = "011" then ++ -- B=0 in *copy* of P pushed onto the stack ++ P(Flag_B) <= '0'; ++ elsif MCycle = "100" then ++ P(Flag_I) <= '1'; ++ end if; ++ end if; ++ ++ if SO_n_o = '1' and SO_n = '0' then ++ P(Flag_V) <= '1'; ++ end if; ++ if RstCycle = '1' and Mode_r /= "00" then ++ P(Flag_1) <= '1'; ++ P(Flag_D) <= '0'; ++ P(Flag_I) <= '1'; ++ end if; ++ P(Flag_1) <= '1'; ++ ++ B_o <= P(Flag_B); ++ SO_n_o <= SO_n; ++ IRQ_n_o <= IRQ_n; ++ NMI_n_o <= NMI_n; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++--------------------------------------------------------------------------- ++-- ++-- Buses ++-- ++--------------------------------------------------------------------------- ++ ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ BusA_r <= (others => '0'); ++ BusB <= (others => '0'); ++ AD <= (others => '0'); ++ BAL <= (others => '0'); ++ BAH <= (others => '0'); ++ DL <= (others => '0'); ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (Rdy = '1') then ++ BusA_r <= BusA; ++ BusB <= DI; ++ ++ case BAAdd is ++ when "01" => ++ -- BA Inc ++ AD <= std_logic_vector(unsigned(AD) + 1); ++ BAL <= std_logic_vector(unsigned(BAL) + 1); ++ when "10" => ++ -- BA Add ++ BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); ++ when "11" => ++ -- BA Adj ++ if BAL(8) = '1' then ++ BAH <= std_logic_vector(unsigned(BAH) + 1); ++ end if; ++ when others => ++ end case; ++ ++ -- ehenciak : modified to use Y register as well (bugfix) ++ if ADAdd = '1' then ++ if (AddY = '1') then ++ AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0))); ++ else ++ AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); ++ end if; ++ end if; ++ ++ if IR = "00000000" then ++ BAL <= (others => '1'); ++ BAH <= (others => '1'); ++ if RstCycle = '1' then ++ BAL(2 downto 0) <= "100"; ++ elsif NMICycle = '1' then ++ BAL(2 downto 0) <= "010"; ++ else ++ BAL(2 downto 0) <= "110"; ++ end if; ++ if Set_addr_To_r = "11" then ++ BAL(0) <= '1'; ++ end if; ++ end if; ++ ++ ++ if LDDI = '1' then ++ DL <= DI; ++ end if; ++ if LDALU = '1' then ++ DL <= ALU_Q; ++ end if; ++ if LDAD = '1' then ++ AD <= DI; ++ end if; ++ if LDBAL = '1' then ++ BAL(7 downto 0) <= DI; ++ end if; ++ if LDBAH = '1' then ++ BAH <= DI; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); ++ ++ ++ with Set_BusA_To select ++ BusA <= DI when "000", ++ ABC(7 downto 0) when "001", ++ X(7 downto 0) when "010", ++ Y(7 downto 0) when "011", ++ std_logic_vector(S(7 downto 0)) when "100", ++ P when "101", ++ (others => '-') when others; ++ ++ with Set_Addr_To_r select ++ A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", ++ DBR & "00000000" & AD when "10", ++ "00000000" & BAH & BAL(7 downto 0) when "11", ++ PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; ++ ++ with Write_Data_r select ++ DO <= DL when "000", ++ ABC(7 downto 0) when "001", ++ X(7 downto 0) when "010", ++ Y(7 downto 0) when "011", ++ std_logic_vector(S(7 downto 0)) when "100", ++ P when "101", ++ std_logic_vector(PC(7 downto 0)) when "110", ++ std_logic_vector(PC(15 downto 8)) when others; ++ ++------------------------------------------------------------------------- ++-- ++-- Main state machine ++-- ++------------------------------------------------------------------------- ++ ++ process (Res_n, Clk) ++ begin ++ if Res_n = '0' then ++ MCycle <= "001"; ++ RstCycle <= '1'; ++ IRQCycle <= '0'; ++ NMICycle <= '0'; ++ NMIAct <= '0'; ++ elsif Clk'event and Clk = '1' then ++ if (Enable = '1') then ++ if (really_rdy = '1') then ++ if MCycle = LCycle or Break = '1' then ++ MCycle <= "000"; ++ RstCycle <= '0'; ++ IRQCycle <= '0'; ++ NMICycle <= '0'; ++ if NMIAct = '1' then ++ NMICycle <= '1'; ++ elsif IRQ_n_o = '0' and P(Flag_I) = '0' then ++ IRQCycle <= '1'; ++ end if; ++ else ++ MCycle <= std_logic_vector(unsigned(MCycle) + 1); ++ end if; ++ ++ if NMICycle = '1' then ++ NMIAct <= '0'; ++ end if; ++ if NMI_n_o = '1' and NMI_n = '0' then ++ NMIAct <= '1'; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++end; +diff --git a/T65/T65_ALU.vhd b/T65/T65_ALU.vhd +index d9d25e1..b1f6d63 100644 +--- a/T65/T65_ALU.vhd ++++ b/T65/T65_ALU.vhd +@@ -1,260 +1,260 @@ +--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 6502 compatible microprocessor core
+---
+--- Version : 0245
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- File history :
+---
+--- 0245 : First version
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-use IEEE.numeric_std.all;
+-use work.T65_Pack.all;
+-
+-entity T65_ALU is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
+-end T65_ALU;
+-
+-architecture rtl of T65_ALU is
+-
+- -- AddSub variables (temporary signals)
+- signal ADC_Z : std_logic;
+- signal ADC_C : std_logic;
+- signal ADC_V : std_logic;
+- signal ADC_N : std_logic;
+- signal ADC_Q : std_logic_vector(7 downto 0);
+- signal SBC_Z : std_logic;
+- signal SBC_C : std_logic;
+- signal SBC_V : std_logic;
+- signal SBC_N : std_logic;
+- signal SBC_Q : std_logic_vector(7 downto 0);
+-
+-begin
+-
+- process (P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(6 downto 0);
+- variable C : std_logic;
+- begin
+- AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
+- AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+--- pragma translate_on
+-
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- ADC_Z <= '1';
+- else
+- ADC_Z <= '0';
+- end if;
+-
+- if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AL(6 downto 1) := AL(6 downto 1) + 6;
+- end if;
+-
+- C := AL(6) or AL(5);
+- AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+-
+- ADC_N <= AH(4);
+- ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+--- pragma translate_on
+-
+- if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AH(6 downto 1) := AH(6 downto 1) + 6;
+- end if;
+-
+- ADC_C <= AH(6) or AH(5);
+-
+- ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
+-
+- process (Op, P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(5 downto 0);
+- variable C : std_logic;
+- begin
+- C := P_In(Flag_C) or not Op(0);
+- AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
+--- pragma translate_on
+-
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- SBC_Z <= '1';
+- else
+- SBC_Z <= '0';
+- end if;
+-
+- SBC_C <= not AH(5);
+- SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
+- SBC_N <= AH(4);
+-
+- if P_In(Flag_D) = '1' then
+- if AL(5) = '1' then
+- AL(5 downto 1) := AL(5 downto 1) - 6;
+- end if;
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
+- if AH(5) = '1' then
+- AH(5 downto 1) := AH(5 downto 1) - 6;
+- end if;
+- end if;
+-
+- SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
+-
+- process (Op, P_In, BusA, BusB,
+- ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
+- SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
+- variable Q_t : std_logic_vector(7 downto 0);
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- P_Out <= P_In;
+- Q_t := BusA;
+- case Op(3 downto 0) is
+- when "0000" =>
+- -- ORA
+- Q_t := BusA or BusB;
+- when "0001" =>
+- -- AND
+- Q_t := BusA and BusB;
+- when "0010" =>
+- -- EOR
+- Q_t := BusA xor BusB;
+- when "0011" =>
+- -- ADC
+- P_Out(Flag_V) <= ADC_V;
+- P_Out(Flag_C) <= ADC_C;
+- Q_t := ADC_Q;
+- when "0101" | "1101" =>
+- -- LDA
+- when "0110" =>
+- -- CMP
+- P_Out(Flag_C) <= SBC_C;
+- when "0111" =>
+- -- SBC
+- P_Out(Flag_V) <= SBC_V;
+- P_Out(Flag_C) <= SBC_C;
+- Q_t := SBC_Q;
+- when "1000" =>
+- -- ASL
+- Q_t := BusA(6 downto 0) & "0";
+- P_Out(Flag_C) <= BusA(7);
+- when "1001" =>
+- -- ROL
+- Q_t := BusA(6 downto 0) & P_In(Flag_C);
+- P_Out(Flag_C) <= BusA(7);
+- when "1010" =>
+- -- LSR
+- Q_t := "0" & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1011" =>
+- -- ROR
+- Q_t := P_In(Flag_C) & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1100" =>
+- -- BIT
+- P_Out(Flag_V) <= BusB(6);
+- when "1110" =>
+- -- DEC
+- Q_t := std_logic_vector(unsigned(BusA) - 1);
+- when "1111" =>
+- -- INC
+- Q_t := std_logic_vector(unsigned(BusA) + 1);
+- when others =>
+- end case;
+-
+- case Op(3 downto 0) is
+- when "0011" =>
+- P_Out(Flag_N) <= ADC_N;
+- P_Out(Flag_Z) <= ADC_Z;
+- when "0110" | "0111" =>
+- P_Out(Flag_N) <= SBC_N;
+- P_Out(Flag_Z) <= SBC_Z;
+- when "0100" =>
+- when "1100" =>
+- P_Out(Flag_N) <= BusB(7);
+- if (BusA and BusB) = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- when others =>
+- P_Out(Flag_N) <= Q_t(7);
+- if Q_t = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- end case;
+-
+- Q <= Q_t;
+- end process;
+-
+-end;
++-- **** ++-- T65(b) core. In an effort to merge and maintain bug fixes .... ++-- ++-- ++-- Ver 300 Bugfixes by ehenciak added ++-- MikeJ March 2005 ++-- Latest version from www.fpgaarcade.com (original www.opencores.org) ++-- ++-- **** ++-- ++-- 6502 compatible microprocessor core ++-- ++-- Version : 0245 ++-- ++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written permission. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- Please report bugs to the author, but before you do so, please ++-- make sure that this is not a derivative work and that ++-- you have the latest version of this file. ++-- ++-- The latest version of this file can be found at: ++-- http://www.opencores.org/cvsweb.shtml/t65/ ++-- ++-- Limitations : ++-- ++-- File history : ++-- ++-- 0245 : First version ++-- ++ ++library IEEE; ++use IEEE.std_logic_1164.all; ++use IEEE.numeric_std.all; ++use work.T65_Pack.all; ++ ++entity T65_ALU is ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ Op : in std_logic_vector(3 downto 0); ++ BusA : in std_logic_vector(7 downto 0); ++ BusB : in std_logic_vector(7 downto 0); ++ P_In : in std_logic_vector(7 downto 0); ++ P_Out : out std_logic_vector(7 downto 0); ++ Q : out std_logic_vector(7 downto 0) ++ ); ++end T65_ALU; ++ ++architecture rtl of T65_ALU is ++ ++ -- AddSub variables (temporary signals) ++ signal ADC_Z : std_logic; ++ signal ADC_C : std_logic; ++ signal ADC_V : std_logic; ++ signal ADC_N : std_logic; ++ signal ADC_Q : std_logic_vector(7 downto 0); ++ signal SBC_Z : std_logic; ++ signal SBC_C : std_logic; ++ signal SBC_V : std_logic; ++ signal SBC_N : std_logic; ++ signal SBC_Q : std_logic_vector(7 downto 0); ++ ++begin ++ ++ process (P_In, BusA, BusB) ++ variable AL : unsigned(6 downto 0); ++ variable AH : unsigned(6 downto 0); ++ variable C : std_logic; ++ begin ++ AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); ++ AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); ++ ++-- pragma translate_off ++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; ++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; ++-- pragma translate_on ++ ++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then ++ ADC_Z <= '1'; ++ else ++ ADC_Z <= '0'; ++ end if; ++ ++ if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then ++ AL(6 downto 1) := AL(6 downto 1) + 6; ++ end if; ++ ++ C := AL(6) or AL(5); ++ AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); ++ ++ ADC_N <= AH(4); ++ ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); ++ ++-- pragma translate_off ++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; ++-- pragma translate_on ++ ++ if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then ++ AH(6 downto 1) := AH(6 downto 1) + 6; ++ end if; ++ ++ ADC_C <= AH(6) or AH(5); ++ ++ ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); ++ end process; ++ ++ process (Op, P_In, BusA, BusB) ++ variable AL : unsigned(6 downto 0); ++ variable AH : unsigned(5 downto 0); ++ variable C : std_logic; ++ begin ++ C := P_In(Flag_C) or not Op(0); ++ AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); ++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); ++ ++-- pragma translate_off ++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; ++ if is_x(std_logic_vector(AH)) then AH := "000000"; end if; ++-- pragma translate_on ++ ++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then ++ SBC_Z <= '1'; ++ else ++ SBC_Z <= '0'; ++ end if; ++ ++ SBC_C <= not AH(5); ++ SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); ++ SBC_N <= AH(4); ++ ++ if P_In(Flag_D) = '1' then ++ if AL(5) = '1' then ++ AL(5 downto 1) := AL(5 downto 1) - 6; ++ end if; ++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); ++ if AH(5) = '1' then ++ AH(5 downto 1) := AH(5 downto 1) - 6; ++ end if; ++ end if; ++ ++ SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); ++ end process; ++ ++ process (Op, P_In, BusA, BusB, ++ ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, ++ SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) ++ variable Q_t : std_logic_vector(7 downto 0); ++ begin ++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC ++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC ++ P_Out <= P_In; ++ Q_t := BusA; ++ case Op(3 downto 0) is ++ when "0000" => ++ -- ORA ++ Q_t := BusA or BusB; ++ when "0001" => ++ -- AND ++ Q_t := BusA and BusB; ++ when "0010" => ++ -- EOR ++ Q_t := BusA xor BusB; ++ when "0011" => ++ -- ADC ++ P_Out(Flag_V) <= ADC_V; ++ P_Out(Flag_C) <= ADC_C; ++ Q_t := ADC_Q; ++ when "0101" | "1101" => ++ -- LDA ++ when "0110" => ++ -- CMP ++ P_Out(Flag_C) <= SBC_C; ++ when "0111" => ++ -- SBC ++ P_Out(Flag_V) <= SBC_V; ++ P_Out(Flag_C) <= SBC_C; ++ Q_t := SBC_Q; ++ when "1000" => ++ -- ASL ++ Q_t := BusA(6 downto 0) & "0"; ++ P_Out(Flag_C) <= BusA(7); ++ when "1001" => ++ -- ROL ++ Q_t := BusA(6 downto 0) & P_In(Flag_C); ++ P_Out(Flag_C) <= BusA(7); ++ when "1010" => ++ -- LSR ++ Q_t := "0" & BusA(7 downto 1); ++ P_Out(Flag_C) <= BusA(0); ++ when "1011" => ++ -- ROR ++ Q_t := P_In(Flag_C) & BusA(7 downto 1); ++ P_Out(Flag_C) <= BusA(0); ++ when "1100" => ++ -- BIT ++ P_Out(Flag_V) <= BusB(6); ++ when "1110" => ++ -- DEC ++ Q_t := std_logic_vector(unsigned(BusA) - 1); ++ when "1111" => ++ -- INC ++ Q_t := std_logic_vector(unsigned(BusA) + 1); ++ when others => ++ end case; ++ ++ case Op(3 downto 0) is ++ when "0011" => ++ P_Out(Flag_N) <= ADC_N; ++ P_Out(Flag_Z) <= ADC_Z; ++ when "0110" | "0111" => ++ P_Out(Flag_N) <= SBC_N; ++ P_Out(Flag_Z) <= SBC_Z; ++ when "0100" => ++ when "1100" => ++ P_Out(Flag_N) <= BusB(7); ++ if (BusA and BusB) = "00000000" then ++ P_Out(Flag_Z) <= '1'; ++ else ++ P_Out(Flag_Z) <= '0'; ++ end if; ++ when others => ++ P_Out(Flag_N) <= Q_t(7); ++ if Q_t = "00000000" then ++ P_Out(Flag_Z) <= '1'; ++ else ++ P_Out(Flag_Z) <= '0'; ++ end if; ++ end case; ++ ++ Q <= Q_t; ++ end process; ++ ++end; +diff --git a/T65/T65_MCode.vhd b/T65/T65_MCode.vhd +index 3fd40d8..6c6c864 100644 +--- a/T65/T65_MCode.vhd ++++ b/T65/T65_MCode.vhd +@@ -1,1052 +1,1052 @@ +--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 302 minor timing fixes
+--- Ver 301 Jump timing fixed
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246 + fix
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- 65C02
+--- supported : inc, dec, phx, plx, phy, ply
+--- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
+---
+--- File history :
+---
+--- 0246 : First release
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-use IEEE.numeric_std.all;
+-use work.T65_Pack.all;
+-
+-entity T65_MCode is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
+-end T65_MCode;
+-
+-architecture rtl of T65_MCode is
+-
+- signal Branch : std_logic;
+-
+-begin
+-
+- with IR(7 downto 5) select
+- Branch <= not P(Flag_N) when "000",
+- P(Flag_N) when "001",
+- not P(Flag_V) when "010",
+- P(Flag_V) when "011",
+- not P(Flag_C) when "100",
+- P(Flag_C) when "101",
+- not P(Flag_Z) when "110",
+- P(Flag_Z) when others;
+-
+- process (IR, MCycle, P, Branch, Mode)
+- begin
+- LCycle <= "001";
+- Set_BusA_To <= "001"; -- A
+- Set_Addr_To <= (others => '0');
+- Write_Data <= (others => '0');
+- Jump <= (others => '0');
+- BAAdd <= "00";
+- BreakAtNA <= '0';
+- ADAdd <= '0';
+- PCAdd <= '0';
+- Inc_S <= '0';
+- Dec_S <= '0';
+- LDA <= '0';
+- LDP <= '0';
+- LDX <= '0';
+- LDY <= '0';
+- LDS <= '0';
+- LDDI <= '0';
+- LDALU <= '0';
+- LDAD <= '0';
+- LDBAL <= '0';
+- LDBAH <= '0';
+- SaveP <= '0';
+- Write <= '0';
+- AddY <= '0';
+-
+- case IR(7 downto 5) is
+- when "100" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- Set_BusA_To <= "011"; -- Y
+- Write_Data <= "011"; -- Y
+- when "10" =>
+- Set_BusA_To <= "010"; -- X
+- Write_Data <= "010"; -- X
+- when others =>
+- Write_Data <= "001"; -- A
+- end case;
+- --}}}
+- when "101" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) /= '1' or IR(2) /= '0' then
+- LDY <= '1';
+- end if;
+- when "10" =>
+- LDX <= '1';
+- when others =>
+- LDA <= '1';
+- end case;
+- Set_BusA_To <= "000"; -- DI
+- --}}}
+- when "110" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDY <= '1';
+- end if;
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when "111" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDX <= '1';
+- end if;
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when others =>
+- end case;
+-
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- Set_BusA_To <= "000"; -- DI
+- end if;
+-
+- case IR(4 downto 0) is
+- when "00000" | "01000" | "01010" | "11000" | "11010" =>
+- --{{{
+- -- Implied
+- case IR is
+- when "00000000" =>
+- -- BRK
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 2 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "101"; -- P
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDDI <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "00100000" =>
+- -- JSR
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01000000" =>
+- -- RTI
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Set_BusA_To <= "000"; -- DI
+- when 4 =>
+- LDP <= '1';
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01100000" =>
+- -- RTS
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when 5 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "00001000" | "01001000" | "01011010" | "11011010" =>
+- -- PHP, PHA, PHY*, PHX*
+- LCycle <= "010";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- case IR(7 downto 4) is
+- when "0000" =>
+- Write_Data <= "101"; -- P
+- when "0100" =>
+- Write_Data <= "001"; -- A
+- when "0101" =>
+- Write_Data <= "011"; -- Y
+- when "1101" =>
+- Write_Data <= "010"; -- X
+- when others =>
+- end case;
+- Write <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Dec_S <= '1';
+- when others =>
+- end case;
+- when "00101000" | "01101000" | "01111010" | "11111010" =>
+- -- PLP, PLA, PLY*, PLX*
+- LCycle <= "011";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case IR(7 downto 4) is
+- when "0010" =>
+- LDP <= '1';
+- when "0110" =>
+- LDA <= '1';
+- when "0111" =>
+- if Mode /= "00" then
+- LDY <= '1';
+- end if;
+- when "1111" =>
+- if Mode /= "00" then
+- LDX <= '1';
+- end if;
+- when others =>
+- end case;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- SaveP <= '1';
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Set_BusA_To <= "000"; -- DI
+- when others =>
+- end case;
+- when "10100000" | "11000000" | "11100000" =>
+- -- LDY, CPY, CPX
+- -- Immediate
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "10001000" =>
+- -- DEY
+- LDY <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- end case;
+- when "11001010" =>
+- -- DEX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- end case;
+- when "00011010" | "00111010" =>
+- -- INC*, DEC*
+- if Mode /= "00" then
+- LDA <= '1'; -- A
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
+- when "00001010" | "00101010" | "01001010" | "01101010" =>
+- -- ASL, ROL, LSR, ROR
+- LDA <= '1'; -- A
+- Set_BusA_To <= "001"; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10001010" | "10011000" =>
+- -- TYA, TXA
+- LDA <= '1'; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10101010" | "10101000" =>
+- -- TAX, TAY
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "001"; -- A
+- when others =>
+- end case;
+- when "10011010" =>
+- -- TXS
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- LDS <= '1';
+- when 1 =>
+- when others =>
+- end case;
+- when "10111010" =>
+- -- TSX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
+-
+- -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
+- -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
+- -- case to_integer(unsigned(MCycle)) is
+- -- when 1 =>
+- -- when others =>
+- -- end case;
+- when others =>
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when others =>
+- end case;
+- end case;
+- --}}}
+-
+- when "00001" | "00011" =>
+- --{{{
+- -- Zero Page Indexed Indirect (d,x)
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- BAAdd <= "01"; -- DB Inc
+- LDBAL <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "01001" | "01011" =>
+- --{{{
+- -- Immediate
+- LDA <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
+-
+- --}}}
+-
+- when "00010" | "10010" =>
+- --{{{
+- -- Immediate, KIL
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- if IR = "10100010" then
+- -- LDX
+- Jump <= "01";
+- else
+- -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+- end if;
+- when others =>
+- end case;
+- --}}}
+-
+- when "00100" =>
+- --{{{
+- -- Zero Page
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "00101" | "00110" | "00111" =>
+- --{{{
+- -- Zero Page
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "100";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "010";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "01100" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
+- -- JMP
+- if IR(5) = '0' then
+- --LCycle <= "011";
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- when 2 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- else
+- --LCycle <= "101";
+- LCycle <= "100"; -- mikej
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- LDBAL <= '1';
+- when 2 =>
+- LDBAH <= '1';
+- if Mode /= "00" then
+- Jump <= "10"; -- DIDL
+- end if;
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- end if;
+- when 3 =>
+- LDDI <= '1';
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- BAAdd <= "01"; -- DB Inc
+- else
+- Jump <= "01";
+- end if;
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- end if;
+- else
+- LCycle <= "011";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "01101" | "01110" | "01111" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- Write <= '1';
+- LDALU <= '1';
+- SaveP <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- SaveP <= '0'; -- MIKEJ was 1
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "10000" =>
+- --{{{
+- -- Relative
+-
+- -- This circuit dictates when the last
+- -- microcycle occurs for the branch depending on
+- -- whether or not the branch is taken and if a page
+- -- is crossed...
+- if (Branch = '1') then
+-
+- LCycle <= "011"; -- We're done @ T3 if branching...upper
+- -- level logic will stop at T2 if no page cross
+- -- (See the Break signal)
+- else
+-
+- LCycle <= "001";
+-
+- end if;
+-
+- -- This decodes the current microcycle and takes the
+- -- proper course of action...
+- case to_integer(unsigned(MCycle)) is
+-
+- -- On the T1 microcycle, increment the program counter
+- -- and instruct the upper level logic to fetch the offset
+- -- from the Din bus and store it in the data latches. This
+- -- will be the last microcycle if the branch isn't taken.
+- when 1 =>
+-
+- Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
+- -- from microcycle T0.
+-
+- LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
+- -- the Din bus to the memory data latch (DL)
+- -- so that the branch offset is fetched.
+-
+- -- In microcycle T2, tell the logic in the top level to
+- -- add the offset. If the most significant byte of the
+- -- program counter (i.e. the current "page") does not need
+- -- updating, we are done here...the Break signal at the
+- -- T65.vhd level takes care of that...
+- when 2 =>
+-
+- Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
+-
+- PCAdd <= '1'; -- This tells the PC adder to update itself with
+- -- the current offset recently fetched from
+- -- memory.
+-
+- -- The following is microcycle T3 :
+- -- The program counter should be completely updated
+- -- on this cycle after the page cross is detected.
+- -- We don't need to do anything here...
+- when 3 =>
+-
+-
+- when others => null; -- Do nothing.
+-
+- end case;
+- --}}}
+-
+- when "10001" | "10011" =>
+- --{{{
+- -- Zero Page Indirect Indexed (d),y
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDBAL <= '1';
+- BAAdd <= "01"; -- DB Inc
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- BAAdd <= "11"; -- BA Adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "10100" | "10101" | "10110" | "10111" =>
+- --{{{
+- -- Zero Page, X
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 5 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- -- Added this check for Y reg. use...
+- if (IR(3 downto 0) = "0110") then
+- AddY <= '1';
+- end if;
+-
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 3 => null;
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "11001" | "11011" =>
+- --{{{
+- -- Absolute Y
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "11100" | "11101" | "11110" | "11111" =>
+- --{{{
+- -- Absolute X
+-
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "010"; -- X
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- -- mikej
+- -- special case 0xBE which uses Y reg as index!!
+- if (IR = "10111110") then
+- Set_BusA_To <= "011"; -- Y
+- else
+- Set_BusA_To <= "010"; -- X
+- end if;
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+- when others =>
+- end case;
+- end process;
+-
+- process (IR, MCycle)
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- case IR(1 downto 0) is
+- when "00" =>
+- --{{{
+- case IR(4 downto 2) is
+- when "000" | "001" | "011" =>
+- case IR(7 downto 5) is
+- when "110" | "111" =>
+- -- CP
+- ALU_Op <= "0110";
+- when "101" =>
+- -- LD
+- ALU_Op <= "0101";
+- when "001" =>
+- -- BIT
+- ALU_Op <= "1100";
+- when others =>
+- -- NOP/ST
+- ALU_Op <= "0100";
+- end case;
+- when "010" =>
+- case IR(7 downto 5) is
+- when "111" | "110" =>
+- -- IN
+- ALU_Op <= "1111";
+- when "100" =>
+- -- DEY
+- ALU_Op <= "1110";
+- when others =>
+- -- LD
+- ALU_Op <= "1101";
+- end case;
+- when "110" =>
+- case IR(7 downto 5) is
+- when "100" =>
+- -- TYA
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "----";
+- end case;
+- when others =>
+- case IR(7 downto 5) is
+- when "101" =>
+- -- LD
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "0100";
+- end case;
+- end case;
+- --}}}
+- when "01" => -- OR
+- --{{{
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- --}}}
+- when "10" =>
+- --{{{
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- case IR(7 downto 5) is
+- when "000" =>
+- if IR(4 downto 2) = "110" then
+- -- INC
+- ALU_Op <= "1111";
+- end if;
+- when "001" =>
+- if IR(4 downto 2) = "110" then
+- -- DEC
+- ALU_Op <= "1110";
+- end if;
+- when "100" =>
+- if IR(4 downto 2) = "010" then
+- -- TXA
+- ALU_Op <= "0101";
+- else
+- ALU_Op <= "0100";
+- end if;
+- when others =>
+- end case;
+- --}}}
+- when others =>
+- --{{{
+- case IR(7 downto 5) is
+- when "100" =>
+- ALU_Op <= "0100";
+- when others =>
+- if MCycle = "000" then
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- else
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- end if;
+- end case;
+- --}}}
+- end case;
+- end process;
+-
+-end;
++-- **** ++-- T65(b) core. In an effort to merge and maintain bug fixes .... ++-- ++-- ++-- Ver 302 minor timing fixes ++-- Ver 301 Jump timing fixed ++-- Ver 300 Bugfixes by ehenciak added ++-- MikeJ March 2005 ++-- Latest version from www.fpgaarcade.com (original www.opencores.org) ++-- ++-- **** ++-- ++-- 65xx compatible microprocessor core ++-- ++-- Version : 0246 + fix ++-- ++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written permission. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- Please report bugs to the author, but before you do so, please ++-- make sure that this is not a derivative work and that ++-- you have the latest version of this file. ++-- ++-- The latest version of this file can be found at: ++-- http://www.opencores.org/cvsweb.shtml/t65/ ++-- ++-- Limitations : ++-- ++-- 65C02 ++-- supported : inc, dec, phx, plx, phy, ply ++-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8 ++-- ++-- File history : ++-- ++-- 0246 : First release ++-- ++ ++library IEEE; ++use IEEE.std_logic_1164.all; ++use IEEE.numeric_std.all; ++use work.T65_Pack.all; ++ ++entity T65_MCode is ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ IR : in std_logic_vector(7 downto 0); ++ MCycle : in std_logic_vector(2 downto 0); ++ P : in std_logic_vector(7 downto 0); ++ LCycle : out std_logic_vector(2 downto 0); ++ ALU_Op : out std_logic_vector(3 downto 0); ++ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P ++ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA ++ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH ++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel ++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj ++ BreakAtNA : out std_logic; ++ ADAdd : out std_logic; ++ AddY : out std_logic; ++ PCAdd : out std_logic; ++ Inc_S : out std_logic; ++ Dec_S : out std_logic; ++ LDA : out std_logic; ++ LDP : out std_logic; ++ LDX : out std_logic; ++ LDY : out std_logic; ++ LDS : out std_logic; ++ LDDI : out std_logic; ++ LDALU : out std_logic; ++ LDAD : out std_logic; ++ LDBAL : out std_logic; ++ LDBAH : out std_logic; ++ SaveP : out std_logic; ++ Write : out std_logic ++ ); ++end T65_MCode; ++ ++architecture rtl of T65_MCode is ++ ++ signal Branch : std_logic; ++ ++begin ++ ++ with IR(7 downto 5) select ++ Branch <= not P(Flag_N) when "000", ++ P(Flag_N) when "001", ++ not P(Flag_V) when "010", ++ P(Flag_V) when "011", ++ not P(Flag_C) when "100", ++ P(Flag_C) when "101", ++ not P(Flag_Z) when "110", ++ P(Flag_Z) when others; ++ ++ process (IR, MCycle, P, Branch, Mode) ++ begin ++ LCycle <= "001"; ++ Set_BusA_To <= "001"; -- A ++ Set_Addr_To <= (others => '0'); ++ Write_Data <= (others => '0'); ++ Jump <= (others => '0'); ++ BAAdd <= "00"; ++ BreakAtNA <= '0'; ++ ADAdd <= '0'; ++ PCAdd <= '0'; ++ Inc_S <= '0'; ++ Dec_S <= '0'; ++ LDA <= '0'; ++ LDP <= '0'; ++ LDX <= '0'; ++ LDY <= '0'; ++ LDS <= '0'; ++ LDDI <= '0'; ++ LDALU <= '0'; ++ LDAD <= '0'; ++ LDBAL <= '0'; ++ LDBAH <= '0'; ++ SaveP <= '0'; ++ Write <= '0'; ++ AddY <= '0'; ++ ++ case IR(7 downto 5) is ++ when "100" => ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ Set_BusA_To <= "011"; -- Y ++ Write_Data <= "011"; -- Y ++ when "10" => ++ Set_BusA_To <= "010"; -- X ++ Write_Data <= "010"; -- X ++ when others => ++ Write_Data <= "001"; -- A ++ end case; ++ --}}} ++ when "101" => ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) /= '1' or IR(2) /= '0' then ++ LDY <= '1'; ++ end if; ++ when "10" => ++ LDX <= '1'; ++ when others => ++ LDA <= '1'; ++ end case; ++ Set_BusA_To <= "000"; -- DI ++ --}}} ++ when "110" => ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) = '0' then ++ LDY <= '1'; ++ end if; ++ Set_BusA_To <= "011"; -- Y ++ when others => ++ Set_BusA_To <= "001"; -- A ++ end case; ++ --}}} ++ when "111" => ++ --{{{ ++ case IR(1 downto 0) is ++ when "00" => ++ if IR(4) = '0' then ++ LDX <= '1'; ++ end if; ++ Set_BusA_To <= "010"; -- X ++ when others => ++ Set_BusA_To <= "001"; -- A ++ end case; ++ --}}} ++ when others => ++ end case; ++ ++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then ++ Set_BusA_To <= "000"; -- DI ++ end if; ++ ++ case IR(4 downto 0) is ++ when "00000" | "01000" | "01010" | "11000" | "11010" => ++ --{{{ ++ -- Implied ++ case IR is ++ when "00000000" => ++ -- BRK ++ LCycle <= "110"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= "01"; -- S ++ Write_Data <= "111"; -- PCH ++ Write <= '1'; ++ when 2 => ++ Dec_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ Write_Data <= "110"; -- PCL ++ Write <= '1'; ++ when 3 => ++ Dec_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ Write_Data <= "101"; -- P ++ Write <= '1'; ++ when 4 => ++ Dec_S <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 5 => ++ LDDI <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 6 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "00100000" => ++ -- JSR ++ LCycle <= "101"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 2 => ++ Set_Addr_To <= "01"; -- S ++ Write_Data <= "111"; -- PCH ++ Write <= '1'; ++ when 3 => ++ Dec_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ Write_Data <= "110"; -- PCL ++ Write <= '1'; ++ when 4 => ++ Dec_S <= '1'; ++ when 5 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "01000000" => ++ -- RTI ++ LCycle <= "101"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= "01"; -- S ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 3 => ++ Inc_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ Set_BusA_To <= "000"; -- DI ++ when 4 => ++ LDP <= '1'; ++ Inc_S <= '1'; ++ LDDI <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 5 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ when "01100000" => ++ -- RTS ++ LCycle <= "101"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Set_Addr_To <= "01"; -- S ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 3 => ++ Inc_S <= '1'; ++ LDDI <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 4 => ++ Jump <= "10"; -- DIDL ++ when 5 => ++ Jump <= "01"; ++ when others => ++ end case; ++ when "00001000" | "01001000" | "01011010" | "11011010" => ++ -- PHP, PHA, PHY*, PHX* ++ LCycle <= "010"; ++ if Mode = "00" and IR(1) = '1' then ++ LCycle <= "001"; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ case IR(7 downto 4) is ++ when "0000" => ++ Write_Data <= "101"; -- P ++ when "0100" => ++ Write_Data <= "001"; -- A ++ when "0101" => ++ Write_Data <= "011"; -- Y ++ when "1101" => ++ Write_Data <= "010"; -- X ++ when others => ++ end case; ++ Write <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 2 => ++ Dec_S <= '1'; ++ when others => ++ end case; ++ when "00101000" | "01101000" | "01111010" | "11111010" => ++ -- PLP, PLA, PLY*, PLX* ++ LCycle <= "011"; ++ if Mode = "00" and IR(1) = '1' then ++ LCycle <= "001"; ++ end if; ++ case IR(7 downto 4) is ++ when "0010" => ++ LDP <= '1'; ++ when "0110" => ++ LDA <= '1'; ++ when "0111" => ++ if Mode /= "00" then ++ LDY <= '1'; ++ end if; ++ when "1111" => ++ if Mode /= "00" then ++ LDX <= '1'; ++ end if; ++ when others => ++ end case; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ SaveP <= '1'; ++ when 1 => ++ Set_Addr_To <= "01"; -- S ++ when 2 => ++ Inc_S <= '1'; ++ Set_Addr_To <= "01"; -- S ++ when 3 => ++ Set_BusA_To <= "000"; -- DI ++ when others => ++ end case; ++ when "10100000" | "11000000" | "11100000" => ++ -- LDY, CPY, CPX ++ -- Immediate ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ when others => ++ end case; ++ when "10001000" => ++ -- DEY ++ LDY <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= "011"; -- Y ++ when others => ++ end case; ++ when "11001010" => ++ -- DEX ++ LDX <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= "010"; -- X ++ when others => ++ end case; ++ when "00011010" | "00111010" => ++ -- INC*, DEC* ++ if Mode /= "00" then ++ LDA <= '1'; -- A ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= "100"; -- S ++ when others => ++ end case; ++ when "00001010" | "00101010" | "01001010" | "01101010" => ++ -- ASL, ROL, LSR, ROR ++ LDA <= '1'; -- A ++ Set_BusA_To <= "001"; -- A ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ when others => ++ end case; ++ when "10001010" | "10011000" => ++ -- TYA, TXA ++ LDA <= '1'; -- A ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ when others => ++ end case; ++ when "10101010" | "10101000" => ++ -- TAX, TAY ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= "001"; -- A ++ when others => ++ end case; ++ when "10011010" => ++ -- TXS ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ LDS <= '1'; ++ when 1 => ++ when others => ++ end case; ++ when "10111010" => ++ -- TSX ++ LDX <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Set_BusA_To <= "100"; -- S ++ when others => ++ end case; ++ ++ -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" => ++ -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX ++ -- case to_integer(unsigned(MCycle)) is ++ -- when 1 => ++ -- when others => ++ -- end case; ++ when others => ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when others => ++ end case; ++ end case; ++ --}}} ++ ++ when "00001" | "00011" => ++ --{{{ ++ -- Zero Page Indexed Indirect (d,x) ++ LCycle <= "101"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ ADAdd <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 3 => ++ BAAdd <= "01"; -- DB Inc ++ LDBAL <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 4 => ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 5 => ++ when others => ++ end case; ++ --}}} ++ ++ when "01001" | "01011" => ++ --{{{ ++ -- Immediate ++ LDA <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ when others => ++ end case; ++ ++ --}}} ++ ++ when "00010" | "10010" => ++ --{{{ ++ -- Immediate, KIL ++ LDX <= '1'; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ if IR = "10100010" then ++ -- LDX ++ Jump <= "01"; ++ else ++ -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ++ end if; ++ when others => ++ end case; ++ --}}} ++ ++ when "00100" => ++ --{{{ ++ -- Zero Page ++ LCycle <= "010"; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ if IR(7 downto 5) = "001" then ++ SaveP <= '1'; ++ end if; ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ when others => ++ end case; ++ --}}} ++ ++ when "00101" | "00110" | "00111" => ++ --{{{ ++ -- Zero Page ++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then ++ -- Read-Modify-Write ++ LCycle <= "100"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ LDDI <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 3 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 4 => ++ when others => ++ end case; ++ else ++ LCycle <= "010"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ when others => ++ end case; ++ end if; ++ --}}} ++ ++ when "01100" => ++ --{{{ ++ -- Absolute ++ if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then ++ -- JMP ++ if IR(5) = '0' then ++ --LCycle <= "011"; ++ LCycle <= "010"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ when 2 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ else ++ --LCycle <= "101"; ++ LCycle <= "100"; -- mikej ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDDI <= '1'; ++ LDBAL <= '1'; ++ when 2 => ++ LDBAH <= '1'; ++ if Mode /= "00" then ++ Jump <= "10"; -- DIDL ++ end if; ++ if Mode = "00" then ++ Set_Addr_To <= "11"; -- BA ++ end if; ++ when 3 => ++ LDDI <= '1'; ++ if Mode = "00" then ++ Set_Addr_To <= "11"; -- BA ++ BAAdd <= "01"; -- DB Inc ++ else ++ Jump <= "01"; ++ end if; ++ when 4 => ++ Jump <= "10"; -- DIDL ++ when others => ++ end case; ++ end if; ++ else ++ LCycle <= "011"; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ if IR(7 downto 5) = "001" then ++ SaveP <= '1'; ++ end if; ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ when others => ++ end case; ++ end if; ++ --}}} ++ ++ when "01101" | "01110" | "01111" => ++ --{{{ ++ -- Absolute ++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then ++ -- Read-Modify-Write ++ LCycle <= "101"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ LDDI <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 4 => ++ Write <= '1'; ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 5 => ++ SaveP <= '0'; -- MIKEJ was 1 ++ when others => ++ end case; ++ else ++ LCycle <= "011"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ LDBAH <= '1'; ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ when others => ++ end case; ++ end if; ++ --}}} ++ ++ when "10000" => ++ --{{{ ++ -- Relative ++ ++ -- This circuit dictates when the last ++ -- microcycle occurs for the branch depending on ++ -- whether or not the branch is taken and if a page ++ -- is crossed... ++ if (Branch = '1') then ++ ++ LCycle <= "011"; -- We're done @ T3 if branching...upper ++ -- level logic will stop at T2 if no page cross ++ -- (See the Break signal) ++ else ++ ++ LCycle <= "001"; ++ ++ end if; ++ ++ -- This decodes the current microcycle and takes the ++ -- proper course of action... ++ case to_integer(unsigned(MCycle)) is ++ ++ -- On the T1 microcycle, increment the program counter ++ -- and instruct the upper level logic to fetch the offset ++ -- from the Din bus and store it in the data latches. This ++ -- will be the last microcycle if the branch isn't taken. ++ when 1 => ++ ++ Jump <= "01"; -- Increments the PC by one (PC will now be PC+2) ++ -- from microcycle T0. ++ ++ LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route ++ -- the Din bus to the memory data latch (DL) ++ -- so that the branch offset is fetched. ++ ++ -- In microcycle T2, tell the logic in the top level to ++ -- add the offset. If the most significant byte of the ++ -- program counter (i.e. the current "page") does not need ++ -- updating, we are done here...the Break signal at the ++ -- T65.vhd level takes care of that... ++ when 2 => ++ ++ Jump <= "11"; -- Tell the PC Jump logic to use relative mode. ++ ++ PCAdd <= '1'; -- This tells the PC adder to update itself with ++ -- the current offset recently fetched from ++ -- memory. ++ ++ -- The following is microcycle T3 : ++ -- The program counter should be completely updated ++ -- on this cycle after the page cross is detected. ++ -- We don't need to do anything here... ++ when 3 => ++ ++ ++ when others => null; -- Do nothing. ++ ++ end case; ++ --}}} ++ ++ when "10001" | "10011" => ++ --{{{ ++ -- Zero Page Indirect Indexed (d),y ++ LCycle <= "101"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ LDBAL <= '1'; ++ BAAdd <= "01"; -- DB Inc ++ Set_Addr_To <= "10"; -- AD ++ when 3 => ++ Set_BusA_To <= "011"; -- Y ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 4 => ++ BAAdd <= "11"; -- BA Adj ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 5 => ++ when others => ++ end case; ++ --}}} ++ ++ when "10100" | "10101" | "10110" | "10111" => ++ --{{{ ++ -- Zero Page, X ++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then ++ -- Read-Modify-Write ++ LCycle <= "101"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ ADAdd <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 3 => ++ LDDI <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 4 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 5 => ++ when others => ++ end case; ++ else ++ LCycle <= "011"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDAD <= '1'; ++ Set_Addr_To <= "10"; -- AD ++ when 2 => ++ ADAdd <= '1'; ++ -- Added this check for Y reg. use... ++ if (IR(3 downto 0) = "0110") then ++ AddY <= '1'; ++ end if; ++ ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ end if; ++ Set_Addr_To <= "10"; -- AD ++ when 3 => null; ++ when others => ++ end case; ++ end if; ++ --}}} ++ ++ when "11001" | "11011" => ++ --{{{ ++ -- Absolute Y ++ LCycle <= "100"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ Set_BusA_To <= "011"; -- Y ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 4 => ++ when others => ++ end case; ++ --}}} ++ ++ when "11100" | "11101" | "11110" | "11111" => ++ --{{{ ++ -- Absolute X ++ ++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then ++ -- Read-Modify-Write ++ LCycle <= "110"; ++ case to_integer(unsigned(MCycle)) is ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ Set_BusA_To <= "010"; -- X ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++ Set_Addr_To <= "11"; -- BA ++ when 4 => ++ LDDI <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 5 => ++ LDALU <= '1'; ++ SaveP <= '1'; ++ Write <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 6 => ++ when others => ++ end case; ++ else ++ LCycle <= "100"; ++ if IR(7 downto 6) /= "10" then ++ LDA <= '1'; ++ end if; ++ case to_integer(unsigned(MCycle)) is ++ when 0 => ++ when 1 => ++ Jump <= "01"; ++ LDBAL <= '1'; ++ when 2 => ++ Jump <= "01"; ++ -- mikej ++ -- special case 0xBE which uses Y reg as index!! ++ if (IR = "10111110") then ++ Set_BusA_To <= "011"; -- Y ++ else ++ Set_BusA_To <= "010"; -- X ++ end if; ++ BAAdd <= "10"; -- BA Add ++ LDBAH <= '1'; ++ Set_Addr_To <= "11"; -- BA ++ when 3 => ++ BAAdd <= "11"; -- BA adj ++ if IR(7 downto 5) = "100" then ++ Write <= '1'; ++ else ++ BreakAtNA <= '1'; ++ end if; ++ Set_Addr_To <= "11"; -- BA ++ when 4 => ++ when others => ++ end case; ++ end if; ++ --}}} ++ when others => ++ end case; ++ end process; ++ ++ process (IR, MCycle) ++ begin ++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC ++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC ++ case IR(1 downto 0) is ++ when "00" => ++ --{{{ ++ case IR(4 downto 2) is ++ when "000" | "001" | "011" => ++ case IR(7 downto 5) is ++ when "110" | "111" => ++ -- CP ++ ALU_Op <= "0110"; ++ when "101" => ++ -- LD ++ ALU_Op <= "0101"; ++ when "001" => ++ -- BIT ++ ALU_Op <= "1100"; ++ when others => ++ -- NOP/ST ++ ALU_Op <= "0100"; ++ end case; ++ when "010" => ++ case IR(7 downto 5) is ++ when "111" | "110" => ++ -- IN ++ ALU_Op <= "1111"; ++ when "100" => ++ -- DEY ++ ALU_Op <= "1110"; ++ when others => ++ -- LD ++ ALU_Op <= "1101"; ++ end case; ++ when "110" => ++ case IR(7 downto 5) is ++ when "100" => ++ -- TYA ++ ALU_Op <= "1101"; ++ when others => ++ ALU_Op <= "----"; ++ end case; ++ when others => ++ case IR(7 downto 5) is ++ when "101" => ++ -- LD ++ ALU_Op <= "1101"; ++ when others => ++ ALU_Op <= "0100"; ++ end case; ++ end case; ++ --}}} ++ when "01" => -- OR ++ --{{{ ++ ALU_Op(3) <= '0'; ++ ALU_Op(2 downto 0) <= IR(7 downto 5); ++ --}}} ++ when "10" => ++ --{{{ ++ ALU_Op(3) <= '1'; ++ ALU_Op(2 downto 0) <= IR(7 downto 5); ++ case IR(7 downto 5) is ++ when "000" => ++ if IR(4 downto 2) = "110" then ++ -- INC ++ ALU_Op <= "1111"; ++ end if; ++ when "001" => ++ if IR(4 downto 2) = "110" then ++ -- DEC ++ ALU_Op <= "1110"; ++ end if; ++ when "100" => ++ if IR(4 downto 2) = "010" then ++ -- TXA ++ ALU_Op <= "0101"; ++ else ++ ALU_Op <= "0100"; ++ end if; ++ when others => ++ end case; ++ --}}} ++ when others => ++ --{{{ ++ case IR(7 downto 5) is ++ when "100" => ++ ALU_Op <= "0100"; ++ when others => ++ if MCycle = "000" then ++ ALU_Op(3) <= '0'; ++ ALU_Op(2 downto 0) <= IR(7 downto 5); ++ else ++ ALU_Op(3) <= '1'; ++ ALU_Op(2 downto 0) <= IR(7 downto 5); ++ end if; ++ end case; ++ --}}} ++ end case; ++ end process; ++ ++end; +diff --git a/T65/T65_Pack.vhd b/T65/T65_Pack.vhd +index f8d603c..e025e1b 100644 +--- a/T65/T65_Pack.vhd ++++ b/T65/T65_Pack.vhd +@@ -1,117 +1,117 @@ +--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- File history :
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-
+-package T65_Pack is
+-
+- constant Flag_C : integer := 0;
+- constant Flag_Z : integer := 1;
+- constant Flag_I : integer := 2;
+- constant Flag_D : integer := 3;
+- constant Flag_B : integer := 4;
+- constant Flag_1 : integer := 5;
+- constant Flag_V : integer := 6;
+- constant Flag_N : integer := 7;
+-
+- component T65_MCode
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
+- end component;
+-
+- component T65_ALU
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
+- end component;
+-
+-end;
++-- **** ++-- T65(b) core. In an effort to merge and maintain bug fixes .... ++-- ++-- ++-- Ver 300 Bugfixes by ehenciak added ++-- MikeJ March 2005 ++-- Latest version from www.fpgaarcade.com (original www.opencores.org) ++-- ++-- **** ++-- ++-- 65xx compatible microprocessor core ++-- ++-- Version : 0246 ++-- ++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org) ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written permission. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- Please report bugs to the author, but before you do so, please ++-- make sure that this is not a derivative work and that ++-- you have the latest version of this file. ++-- ++-- The latest version of this file can be found at: ++-- http://www.opencores.org/cvsweb.shtml/t65/ ++-- ++-- Limitations : ++-- ++-- File history : ++-- ++ ++library IEEE; ++use IEEE.std_logic_1164.all; ++ ++package T65_Pack is ++ ++ constant Flag_C : integer := 0; ++ constant Flag_Z : integer := 1; ++ constant Flag_I : integer := 2; ++ constant Flag_D : integer := 3; ++ constant Flag_B : integer := 4; ++ constant Flag_1 : integer := 5; ++ constant Flag_V : integer := 6; ++ constant Flag_N : integer := 7; ++ ++ component T65_MCode ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 ++ IR : in std_logic_vector(7 downto 0); ++ MCycle : in std_logic_vector(2 downto 0); ++ P : in std_logic_vector(7 downto 0); ++ LCycle : out std_logic_vector(2 downto 0); ++ ALU_Op : out std_logic_vector(3 downto 0); ++ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P ++ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA ++ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH ++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel ++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj ++ BreakAtNA : out std_logic; ++ ADAdd : out std_logic; ++ AddY : out std_logic; ++ PCAdd : out std_logic; ++ Inc_S : out std_logic; ++ Dec_S : out std_logic; ++ LDA : out std_logic; ++ LDP : out std_logic; ++ LDX : out std_logic; ++ LDY : out std_logic; ++ LDS : out std_logic; ++ LDDI : out std_logic; ++ LDALU : out std_logic; ++ LDAD : out std_logic; ++ LDBAL : out std_logic; ++ LDBAH : out std_logic; ++ SaveP : out std_logic; ++ Write : out std_logic ++ ); ++ end component; ++ ++ component T65_ALU ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 ++ Op : in std_logic_vector(3 downto 0); ++ BusA : in std_logic_vector(7 downto 0); ++ BusB : in std_logic_vector(7 downto 0); ++ P_In : in std_logic_vector(7 downto 0); ++ P_Out : out std_logic_vector(7 downto 0); ++ Q : out std_logic_vector(7 downto 0) ++ ); ++ end component; ++ ++end; +diff --git a/bbc_micro.qpf b/bbc_micro.qpf +index 52e0fd0..c2ade9e 100644 +--- a/bbc_micro.qpf ++++ b/bbc_micro.qpf +@@ -1,30 +1,30 @@ +-# -------------------------------------------------------------------------- #
+-#
+-# Copyright (C) 1991-2009 Altera Corporation
+-# Your use of Altera Corporation's design tools, logic functions
+-# and other software and tools, and its AMPP partner logic
+-# functions, and any output files from any of the foregoing
+-# (including device programming or simulation files), and any
+-# associated documentation or information are expressly subject
+-# to the terms and conditions of the Altera Program License
+-# Subscription Agreement, Altera MegaCore Function License
+-# Agreement, or other applicable license agreement, including,
+-# without limitation, that your use is for the sole purpose of
+-# programming logic devices manufactured by Altera and sold by
+-# Altera or its authorized distributors. Please refer to the
+-# applicable agreement for further details.
+-#
+-# -------------------------------------------------------------------------- #
+-#
+-# Quartus II
+-# Version 9.1 Build 222 10/21/2009 SJ Web Edition
+-# Date created = 20:48:44 July 12, 2011
+-#
+-# -------------------------------------------------------------------------- #
+-
+-QUARTUS_VERSION = "9.1"
+-DATE = "20:48:44 July 12, 2011"
+-
+-# Revisions
+-
+-PROJECT_REVISION = "bbc_micro_de1"
++# -------------------------------------------------------------------------- # ++# ++# Copyright (C) 1991-2009 Altera Corporation ++# Your use of Altera Corporation's design tools, logic functions ++# and other software and tools, and its AMPP partner logic ++# functions, and any output files from any of the foregoing ++# (including device programming or simulation files), and any ++# associated documentation or information are expressly subject ++# to the terms and conditions of the Altera Program License ++# Subscription Agreement, Altera MegaCore Function License ++# Agreement, or other applicable license agreement, including, ++# without limitation, that your use is for the sole purpose of ++# programming logic devices manufactured by Altera and sold by ++# Altera or its authorized distributors. Please refer to the ++# applicable agreement for further details. ++# ++# -------------------------------------------------------------------------- # ++# ++# Quartus II ++# Version 9.1 Build 222 10/21/2009 SJ Web Edition ++# Date created = 20:48:44 July 12, 2011 ++# ++# -------------------------------------------------------------------------- # ++ ++QUARTUS_VERSION = "9.1" ++DATE = "20:48:44 July 12, 2011" ++ ++# Revisions ++ ++PROJECT_REVISION = "bbc_micro_de1" +diff --git a/bbc_micro_de1.qsf b/bbc_micro_de1.qsf +index be8b1f2..0ae4816 100644 +--- a/bbc_micro_de1.qsf ++++ b/bbc_micro_de1.qsf +@@ -1,537 +1,537 @@ +-# -------------------------------------------------------------------------- #
+-#
+-# Copyright (C) 1991-2009 Altera Corporation
+-# Your use of Altera Corporation's design tools, logic functions
+-# and other software and tools, and its AMPP partner logic
+-# functions, and any output files from any of the foregoing
+-# (including device programming or simulation files), and any
+-# associated documentation or information are expressly subject
+-# to the terms and conditions of the Altera Program License
+-# Subscription Agreement, Altera MegaCore Function License
+-# Agreement, or other applicable license agreement, including,
+-# without limitation, that your use is for the sole purpose of
+-# programming logic devices manufactured by Altera and sold by
+-# Altera or its authorized distributors. Please refer to the
+-# applicable agreement for further details.
+-#
+-# -------------------------------------------------------------------------- #
+-#
+-# Quartus II
+-# Version 9.1 Build 222 10/21/2009 SJ Web Edition
+-# Date created = 20:48:44 July 12, 2011
+-#
+-# -------------------------------------------------------------------------- #
+-#
+-# Notes:
+-#
+-# 1) The default values for assignments are stored in the file:
+-# bbc_micro_de1_assignment_defaults.qdf
+-# If this file doesn't exist, see file:
+-# assignment_defaults.qdf
+-#
+-# 2) Altera recommends that you do not modify this file. This
+-# file is updated automatically by the Quartus II software
+-# and any changes you make may be lost or overwritten.
+-#
+-# -------------------------------------------------------------------------- #
+-
+-
+-set_global_assignment -name FAMILY "Cyclone II"
+-set_global_assignment -name DEVICE EP2C20F484C7
+-set_global_assignment -name TOP_LEVEL_ENTITY bbc_micro_de1
+-set_global_assignment -name ORIGINAL_QUARTUS_VERSION 9.1
+-set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:48:44 JULY 12, 2011"
+-set_global_assignment -name LAST_QUARTUS_VERSION 9.1
+-set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga
+-set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
+-set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484
+-set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7
+-set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+-set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+-set_location_assignment PIN_A13 -to GPIO_0[0]
+-set_location_assignment PIN_B13 -to GPIO_0[1]
+-set_location_assignment PIN_A14 -to GPIO_0[2]
+-set_location_assignment PIN_B14 -to GPIO_0[3]
+-set_location_assignment PIN_A15 -to GPIO_0[4]
+-set_location_assignment PIN_B15 -to GPIO_0[5]
+-set_location_assignment PIN_A16 -to GPIO_0[6]
+-set_location_assignment PIN_B16 -to GPIO_0[7]
+-set_location_assignment PIN_A17 -to GPIO_0[8]
+-set_location_assignment PIN_B17 -to GPIO_0[9]
+-set_location_assignment PIN_A18 -to GPIO_0[10]
+-set_location_assignment PIN_B18 -to GPIO_0[11]
+-set_location_assignment PIN_A19 -to GPIO_0[12]
+-set_location_assignment PIN_B19 -to GPIO_0[13]
+-set_location_assignment PIN_A20 -to GPIO_0[14]
+-set_location_assignment PIN_B20 -to GPIO_0[15]
+-set_location_assignment PIN_C21 -to GPIO_0[16]
+-set_location_assignment PIN_C22 -to GPIO_0[17]
+-set_location_assignment PIN_D21 -to GPIO_0[18]
+-set_location_assignment PIN_D22 -to GPIO_0[19]
+-set_location_assignment PIN_E21 -to GPIO_0[20]
+-set_location_assignment PIN_E22 -to GPIO_0[21]
+-set_location_assignment PIN_F21 -to GPIO_0[22]
+-set_location_assignment PIN_F22 -to GPIO_0[23]
+-set_location_assignment PIN_G21 -to GPIO_0[24]
+-set_location_assignment PIN_G22 -to GPIO_0[25]
+-set_location_assignment PIN_J21 -to GPIO_0[26]
+-set_location_assignment PIN_J22 -to GPIO_0[27]
+-set_location_assignment PIN_K21 -to GPIO_0[28]
+-set_location_assignment PIN_K22 -to GPIO_0[29]
+-set_location_assignment PIN_J19 -to GPIO_0[30]
+-set_location_assignment PIN_J20 -to GPIO_0[31]
+-set_location_assignment PIN_J18 -to GPIO_0[32]
+-set_location_assignment PIN_K20 -to GPIO_0[33]
+-set_location_assignment PIN_L19 -to GPIO_0[34]
+-set_location_assignment PIN_L18 -to GPIO_0[35]
+-set_location_assignment PIN_H12 -to GPIO_1[0]
+-set_location_assignment PIN_H13 -to GPIO_1[1]
+-set_location_assignment PIN_H14 -to GPIO_1[2]
+-set_location_assignment PIN_G15 -to GPIO_1[3]
+-set_location_assignment PIN_E14 -to GPIO_1[4]
+-set_location_assignment PIN_E15 -to GPIO_1[5]
+-set_location_assignment PIN_F15 -to GPIO_1[6]
+-set_location_assignment PIN_G16 -to GPIO_1[7]
+-set_location_assignment PIN_F12 -to GPIO_1[8]
+-set_location_assignment PIN_F13 -to GPIO_1[9]
+-set_location_assignment PIN_C14 -to GPIO_1[10]
+-set_location_assignment PIN_D14 -to GPIO_1[11]
+-set_location_assignment PIN_D15 -to GPIO_1[12]
+-set_location_assignment PIN_D16 -to GPIO_1[13]
+-set_location_assignment PIN_C17 -to GPIO_1[14]
+-set_location_assignment PIN_C18 -to GPIO_1[15]
+-set_location_assignment PIN_C19 -to GPIO_1[16]
+-set_location_assignment PIN_C20 -to GPIO_1[17]
+-set_location_assignment PIN_D19 -to GPIO_1[18]
+-set_location_assignment PIN_D20 -to GPIO_1[19]
+-set_location_assignment PIN_E20 -to GPIO_1[20]
+-set_location_assignment PIN_F20 -to GPIO_1[21]
+-set_location_assignment PIN_E19 -to GPIO_1[22]
+-set_location_assignment PIN_E18 -to GPIO_1[23]
+-set_location_assignment PIN_G20 -to GPIO_1[24]
+-set_location_assignment PIN_G18 -to GPIO_1[25]
+-set_location_assignment PIN_G17 -to GPIO_1[26]
+-set_location_assignment PIN_H17 -to GPIO_1[27]
+-set_location_assignment PIN_J15 -to GPIO_1[28]
+-set_location_assignment PIN_H18 -to GPIO_1[29]
+-set_location_assignment PIN_N22 -to GPIO_1[30]
+-set_location_assignment PIN_N21 -to GPIO_1[31]
+-set_location_assignment PIN_P15 -to GPIO_1[32]
+-set_location_assignment PIN_N15 -to GPIO_1[33]
+-set_location_assignment PIN_P17 -to GPIO_1[34]
+-set_location_assignment PIN_P18 -to GPIO_1[35]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[10]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[11]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[12]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[13]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[14]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[15]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[16]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[17]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[18]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[19]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[20]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[21]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[22]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[23]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[24]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[25]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[26]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[27]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[28]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[29]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[30]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[31]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[32]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[33]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[34]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[35]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[10]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[11]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[12]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[13]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[14]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[15]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[16]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[17]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[18]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[19]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[20]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[21]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[22]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[23]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[24]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[25]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[26]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[27]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[28]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[29]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[30]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[31]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[32]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[33]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[34]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[35]
+-set_location_assignment PIN_L22 -to SW[0]
+-set_location_assignment PIN_L21 -to SW[1]
+-set_location_assignment PIN_M22 -to SW[2]
+-set_location_assignment PIN_V12 -to SW[3]
+-set_location_assignment PIN_W12 -to SW[4]
+-set_location_assignment PIN_U12 -to SW[5]
+-set_location_assignment PIN_U11 -to SW[6]
+-set_location_assignment PIN_M2 -to SW[7]
+-set_location_assignment PIN_M1 -to SW[8]
+-set_location_assignment PIN_L2 -to SW[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[9]
+-set_location_assignment PIN_J2 -to HEX0[0]
+-set_location_assignment PIN_J1 -to HEX0[1]
+-set_location_assignment PIN_H2 -to HEX0[2]
+-set_location_assignment PIN_H1 -to HEX0[3]
+-set_location_assignment PIN_F2 -to HEX0[4]
+-set_location_assignment PIN_F1 -to HEX0[5]
+-set_location_assignment PIN_E2 -to HEX0[6]
+-set_location_assignment PIN_E1 -to HEX1[0]
+-set_location_assignment PIN_H6 -to HEX1[1]
+-set_location_assignment PIN_H5 -to HEX1[2]
+-set_location_assignment PIN_H4 -to HEX1[3]
+-set_location_assignment PIN_G3 -to HEX1[4]
+-set_location_assignment PIN_D2 -to HEX1[5]
+-set_location_assignment PIN_D1 -to HEX1[6]
+-set_location_assignment PIN_G5 -to HEX2[0]
+-set_location_assignment PIN_G6 -to HEX2[1]
+-set_location_assignment PIN_C2 -to HEX2[2]
+-set_location_assignment PIN_C1 -to HEX2[3]
+-set_location_assignment PIN_E3 -to HEX2[4]
+-set_location_assignment PIN_E4 -to HEX2[5]
+-set_location_assignment PIN_D3 -to HEX2[6]
+-set_location_assignment PIN_F4 -to HEX3[0]
+-set_location_assignment PIN_D5 -to HEX3[1]
+-set_location_assignment PIN_D6 -to HEX3[2]
+-set_location_assignment PIN_J4 -to HEX3[3]
+-set_location_assignment PIN_L8 -to HEX3[4]
+-set_location_assignment PIN_F3 -to HEX3[5]
+-set_location_assignment PIN_D4 -to HEX3[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[6]
+-set_location_assignment PIN_R22 -to KEY[0]
+-set_location_assignment PIN_R21 -to KEY[1]
+-set_location_assignment PIN_T22 -to KEY[2]
+-set_location_assignment PIN_T21 -to KEY[3]
+-set_location_assignment PIN_R20 -to LEDR[0]
+-set_location_assignment PIN_R19 -to LEDR[1]
+-set_location_assignment PIN_U19 -to LEDR[2]
+-set_location_assignment PIN_Y19 -to LEDR[3]
+-set_location_assignment PIN_T18 -to LEDR[4]
+-set_location_assignment PIN_V19 -to LEDR[5]
+-set_location_assignment PIN_Y18 -to LEDR[6]
+-set_location_assignment PIN_U18 -to LEDR[7]
+-set_location_assignment PIN_R18 -to LEDR[8]
+-set_location_assignment PIN_R17 -to LEDR[9]
+-set_location_assignment PIN_U22 -to LEDG[0]
+-set_location_assignment PIN_U21 -to LEDG[1]
+-set_location_assignment PIN_V22 -to LEDG[2]
+-set_location_assignment PIN_V21 -to LEDG[3]
+-set_location_assignment PIN_W22 -to LEDG[4]
+-set_location_assignment PIN_W21 -to LEDG[5]
+-set_location_assignment PIN_Y22 -to LEDG[6]
+-set_location_assignment PIN_Y21 -to LEDG[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[7]
+-set_location_assignment PIN_D12 -to CLOCK_27[0]
+-set_location_assignment PIN_E12 -to CLOCK_27[1]
+-set_location_assignment PIN_B12 -to CLOCK_24[0]
+-set_location_assignment PIN_A12 -to CLOCK_24[1]
+-set_location_assignment PIN_L1 -to CLOCK_50
+-set_location_assignment PIN_M21 -to EXT_CLOCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_27[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_50
+-set_instance_assignment -name IO_STANDARD LVTTL -to EXT_CLOCK
+-set_location_assignment PIN_H15 -to PS2_CLK
+-set_location_assignment PIN_J14 -to PS2_DAT
+-set_location_assignment PIN_F14 -to UART_RXD
+-set_location_assignment PIN_G12 -to UART_TXD
+-set_instance_assignment -name IO_STANDARD LVTTL -to PS2_CLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to PS2_DAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to UART_RXD
+-set_instance_assignment -name IO_STANDARD LVTTL -to UART_TXD
+-set_location_assignment PIN_E8 -to TDI
+-set_location_assignment PIN_D8 -to TCS
+-set_location_assignment PIN_C7 -to TCK
+-set_location_assignment PIN_D7 -to TDO
+-set_instance_assignment -name IO_STANDARD LVTTL -to TDI
+-set_instance_assignment -name IO_STANDARD LVTTL -to TCS
+-set_instance_assignment -name IO_STANDARD LVTTL -to TCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to TDO
+-set_location_assignment PIN_D9 -to VGA_R[0]
+-set_location_assignment PIN_C9 -to VGA_R[1]
+-set_location_assignment PIN_A7 -to VGA_R[2]
+-set_location_assignment PIN_B7 -to VGA_R[3]
+-set_location_assignment PIN_B8 -to VGA_G[0]
+-set_location_assignment PIN_C10 -to VGA_G[1]
+-set_location_assignment PIN_B9 -to VGA_G[2]
+-set_location_assignment PIN_A8 -to VGA_G[3]
+-set_location_assignment PIN_A9 -to VGA_B[0]
+-set_location_assignment PIN_D11 -to VGA_B[1]
+-set_location_assignment PIN_A10 -to VGA_B[2]
+-set_location_assignment PIN_B10 -to VGA_B[3]
+-set_location_assignment PIN_A11 -to VGA_HS
+-set_location_assignment PIN_B11 -to VGA_VS
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_HS
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_VS
+-set_location_assignment PIN_A3 -to I2C_SCLK
+-set_location_assignment PIN_B3 -to I2C_SDAT
+-set_location_assignment PIN_A6 -to AUD_ADCLRCK
+-set_location_assignment PIN_B6 -to AUD_ADCDAT
+-set_location_assignment PIN_A5 -to AUD_DACLRCK
+-set_location_assignment PIN_B5 -to AUD_DACDAT
+-set_location_assignment PIN_B4 -to AUD_XCK
+-set_location_assignment PIN_A4 -to AUD_BCLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SCLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCLRCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACLRCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_XCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_BCLK
+-set_location_assignment PIN_W4 -to DRAM_ADDR[0]
+-set_location_assignment PIN_W5 -to DRAM_ADDR[1]
+-set_location_assignment PIN_Y3 -to DRAM_ADDR[2]
+-set_location_assignment PIN_Y4 -to DRAM_ADDR[3]
+-set_location_assignment PIN_R6 -to DRAM_ADDR[4]
+-set_location_assignment PIN_R5 -to DRAM_ADDR[5]
+-set_location_assignment PIN_P6 -to DRAM_ADDR[6]
+-set_location_assignment PIN_P5 -to DRAM_ADDR[7]
+-set_location_assignment PIN_P3 -to DRAM_ADDR[8]
+-set_location_assignment PIN_N4 -to DRAM_ADDR[9]
+-set_location_assignment PIN_W3 -to DRAM_ADDR[10]
+-set_location_assignment PIN_N6 -to DRAM_ADDR[11]
+-set_location_assignment PIN_U3 -to DRAM_BA_0
+-set_location_assignment PIN_V4 -to DRAM_BA_1
+-set_location_assignment PIN_T3 -to DRAM_CAS_N
+-set_location_assignment PIN_N3 -to DRAM_CKE
+-set_location_assignment PIN_U4 -to DRAM_CLK
+-set_location_assignment PIN_T6 -to DRAM_CS_N
+-set_location_assignment PIN_U1 -to DRAM_DQ[0]
+-set_location_assignment PIN_U2 -to DRAM_DQ[1]
+-set_location_assignment PIN_V1 -to DRAM_DQ[2]
+-set_location_assignment PIN_V2 -to DRAM_DQ[3]
+-set_location_assignment PIN_W1 -to DRAM_DQ[4]
+-set_location_assignment PIN_W2 -to DRAM_DQ[5]
+-set_location_assignment PIN_Y1 -to DRAM_DQ[6]
+-set_location_assignment PIN_Y2 -to DRAM_DQ[7]
+-set_location_assignment PIN_N1 -to DRAM_DQ[8]
+-set_location_assignment PIN_N2 -to DRAM_DQ[9]
+-set_location_assignment PIN_P1 -to DRAM_DQ[10]
+-set_location_assignment PIN_P2 -to DRAM_DQ[11]
+-set_location_assignment PIN_R1 -to DRAM_DQ[12]
+-set_location_assignment PIN_R2 -to DRAM_DQ[13]
+-set_location_assignment PIN_T1 -to DRAM_DQ[14]
+-set_location_assignment PIN_T2 -to DRAM_DQ[15]
+-set_location_assignment PIN_R7 -to DRAM_LDQM
+-set_location_assignment PIN_T5 -to DRAM_RAS_N
+-set_location_assignment PIN_M5 -to DRAM_UDQM
+-set_location_assignment PIN_R8 -to DRAM_WE_N
+-set_location_assignment PIN_AB20 -to FL_ADDR[0]
+-set_location_assignment PIN_AA14 -to FL_ADDR[1]
+-set_location_assignment PIN_Y16 -to FL_ADDR[2]
+-set_location_assignment PIN_R15 -to FL_ADDR[3]
+-set_location_assignment PIN_T15 -to FL_ADDR[4]
+-set_location_assignment PIN_U15 -to FL_ADDR[5]
+-set_location_assignment PIN_V15 -to FL_ADDR[6]
+-set_location_assignment PIN_W15 -to FL_ADDR[7]
+-set_location_assignment PIN_R14 -to FL_ADDR[8]
+-set_location_assignment PIN_Y13 -to FL_ADDR[9]
+-set_location_assignment PIN_R12 -to FL_ADDR[10]
+-set_location_assignment PIN_T12 -to FL_ADDR[11]
+-set_location_assignment PIN_AB14 -to FL_ADDR[12]
+-set_location_assignment PIN_AA13 -to FL_ADDR[13]
+-set_location_assignment PIN_AB13 -to FL_ADDR[14]
+-set_location_assignment PIN_AA12 -to FL_ADDR[15]
+-set_location_assignment PIN_AB12 -to FL_ADDR[16]
+-set_location_assignment PIN_AA20 -to FL_ADDR[17]
+-set_location_assignment PIN_U14 -to FL_ADDR[18]
+-set_location_assignment PIN_V14 -to FL_ADDR[19]
+-set_location_assignment PIN_U13 -to FL_ADDR[20]
+-set_location_assignment PIN_R13 -to FL_ADDR[21]
+-set_location_assignment PIN_AB16 -to FL_DQ[0]
+-set_location_assignment PIN_AA16 -to FL_DQ[1]
+-set_location_assignment PIN_AB17 -to FL_DQ[2]
+-set_location_assignment PIN_AA17 -to FL_DQ[3]
+-set_location_assignment PIN_AB18 -to FL_DQ[4]
+-set_location_assignment PIN_AA18 -to FL_DQ[5]
+-set_location_assignment PIN_AB19 -to FL_DQ[6]
+-set_location_assignment PIN_AA19 -to FL_DQ[7]
+-set_location_assignment PIN_AA15 -to FL_OE_N
+-set_location_assignment PIN_W14 -to FL_RST_N
+-set_location_assignment PIN_Y14 -to FL_WE_N
+-set_location_assignment PIN_AA3 -to SRAM_ADDR[0]
+-set_location_assignment PIN_AB3 -to SRAM_ADDR[1]
+-set_location_assignment PIN_AA4 -to SRAM_ADDR[2]
+-set_location_assignment PIN_AB4 -to SRAM_ADDR[3]
+-set_location_assignment PIN_AA5 -to SRAM_ADDR[4]
+-set_location_assignment PIN_AB10 -to SRAM_ADDR[5]
+-set_location_assignment PIN_AA11 -to SRAM_ADDR[6]
+-set_location_assignment PIN_AB11 -to SRAM_ADDR[7]
+-set_location_assignment PIN_V11 -to SRAM_ADDR[8]
+-set_location_assignment PIN_W11 -to SRAM_ADDR[9]
+-set_location_assignment PIN_R11 -to SRAM_ADDR[10]
+-set_location_assignment PIN_T11 -to SRAM_ADDR[11]
+-set_location_assignment PIN_Y10 -to SRAM_ADDR[12]
+-set_location_assignment PIN_U10 -to SRAM_ADDR[13]
+-set_location_assignment PIN_R10 -to SRAM_ADDR[14]
+-set_location_assignment PIN_T7 -to SRAM_ADDR[15]
+-set_location_assignment PIN_Y6 -to SRAM_ADDR[16]
+-set_location_assignment PIN_Y5 -to SRAM_ADDR[17]
+-set_location_assignment PIN_AB5 -to SRAM_CE_N
+-set_location_assignment PIN_AA6 -to SRAM_DQ[0]
+-set_location_assignment PIN_AB6 -to SRAM_DQ[1]
+-set_location_assignment PIN_AA7 -to SRAM_DQ[2]
+-set_location_assignment PIN_AB7 -to SRAM_DQ[3]
+-set_location_assignment PIN_AA8 -to SRAM_DQ[4]
+-set_location_assignment PIN_AB8 -to SRAM_DQ[5]
+-set_location_assignment PIN_AA9 -to SRAM_DQ[6]
+-set_location_assignment PIN_AB9 -to SRAM_DQ[7]
+-set_location_assignment PIN_Y9 -to SRAM_DQ[8]
+-set_location_assignment PIN_W9 -to SRAM_DQ[9]
+-set_location_assignment PIN_V9 -to SRAM_DQ[10]
+-set_location_assignment PIN_U9 -to SRAM_DQ[11]
+-set_location_assignment PIN_R9 -to SRAM_DQ[12]
+-set_location_assignment PIN_W8 -to SRAM_DQ[13]
+-set_location_assignment PIN_V8 -to SRAM_DQ[14]
+-set_location_assignment PIN_U8 -to SRAM_DQ[15]
+-set_location_assignment PIN_Y7 -to SRAM_LB_N
+-set_location_assignment PIN_T8 -to SRAM_OE_N
+-set_location_assignment PIN_W7 -to SRAM_UB_N
+-set_location_assignment PIN_AA10 -to SRAM_WE_N
+-set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED WITH WEAK PULL-UP"
+-set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+-set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+-set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
+-set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
+-set_global_assignment -name MISC_FILE "U:/git_repos/fpga/bbc/bbc_micro_de1.dpf"
+-set_location_assignment PIN_AB15 -to FL_CE_N
+-set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
+-set_global_assignment -name STRATIX_CONFIGURATION_DEVICE EPCS4
+-set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED"
+-set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+-set_location_assignment PIN_U20 -to SD_nCS
+-set_location_assignment PIN_V20 -to SD_SCLK
+-set_location_assignment PIN_Y20 -to SD_MOSI
+-set_location_assignment PIN_W20 -to SD_MISO
+-set_global_assignment -name VHDL_FILE saa5050.vhd
+-set_global_assignment -name VHDL_FILE i2s_intf.vhd
+-set_global_assignment -name VHDL_FILE i2c_loader.vhd
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_comp_pack-p.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_noise.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_tone.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_top.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_attenuator.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_clock_div.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_latch_ctrl.vhd"
+-set_global_assignment -name VHDL_FILE ps2_intf.vhd
+-set_global_assignment -name VHDL_FILE m6522.vhd
+-set_global_assignment -name VHDL_FILE seg7.vhd
+-set_global_assignment -name VHDL_FILE vidproc.vhd
+-set_global_assignment -name VHDL_FILE mc6845.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_Pack.vhd
+-set_global_assignment -name VHDL_FILE T65/T65.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_ALU.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_MCode.vhd
+-set_global_assignment -name QIP_FILE pll32.qip
+-set_global_assignment -name VHDL_FILE bbc_micro_de1.vhd
+-set_global_assignment -name VHDL_FILE bbc_micro_de1_tb.vhd
+-set_global_assignment -name VHDL_FILE m6522_tb.vhd
+-set_global_assignment -name VHDL_FILE keyboard.vhd
+-set_global_assignment -name VHDL_FILE debugger.vhd
+-set_global_assignment -name QIP_FILE saa5050_rom.qip
++# -------------------------------------------------------------------------- # ++# ++# Copyright (C) 1991-2009 Altera Corporation ++# Your use of Altera Corporation's design tools, logic functions ++# and other software and tools, and its AMPP partner logic ++# functions, and any output files from any of the foregoing ++# (including device programming or simulation files), and any ++# associated documentation or information are expressly subject ++# to the terms and conditions of the Altera Program License ++# Subscription Agreement, Altera MegaCore Function License ++# Agreement, or other applicable license agreement, including, ++# without limitation, that your use is for the sole purpose of ++# programming logic devices manufactured by Altera and sold by ++# Altera or its authorized distributors. Please refer to the ++# applicable agreement for further details. ++# ++# -------------------------------------------------------------------------- # ++# ++# Quartus II ++# Version 9.1 Build 222 10/21/2009 SJ Web Edition ++# Date created = 20:48:44 July 12, 2011 ++# ++# -------------------------------------------------------------------------- # ++# ++# Notes: ++# ++# 1) The default values for assignments are stored in the file: ++# bbc_micro_de1_assignment_defaults.qdf ++# If this file doesn't exist, see file: ++# assignment_defaults.qdf ++# ++# 2) Altera recommends that you do not modify this file. This ++# file is updated automatically by the Quartus II software ++# and any changes you make may be lost or overwritten. ++# ++# -------------------------------------------------------------------------- # ++ ++ ++set_global_assignment -name FAMILY "Cyclone II" ++set_global_assignment -name DEVICE EP2C20F484C7 ++set_global_assignment -name TOP_LEVEL_ENTITY bbc_micro_de1 ++set_global_assignment -name ORIGINAL_QUARTUS_VERSION 9.1 ++set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:48:44 JULY 12, 2011" ++set_global_assignment -name LAST_QUARTUS_VERSION 9.1 ++set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga ++set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA ++set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484 ++set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 ++set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 ++set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 ++set_location_assignment PIN_A13 -to GPIO_0[0] ++set_location_assignment PIN_B13 -to GPIO_0[1] ++set_location_assignment PIN_A14 -to GPIO_0[2] ++set_location_assignment PIN_B14 -to GPIO_0[3] ++set_location_assignment PIN_A15 -to GPIO_0[4] ++set_location_assignment PIN_B15 -to GPIO_0[5] ++set_location_assignment PIN_A16 -to GPIO_0[6] ++set_location_assignment PIN_B16 -to GPIO_0[7] ++set_location_assignment PIN_A17 -to GPIO_0[8] ++set_location_assignment PIN_B17 -to GPIO_0[9] ++set_location_assignment PIN_A18 -to GPIO_0[10] ++set_location_assignment PIN_B18 -to GPIO_0[11] ++set_location_assignment PIN_A19 -to GPIO_0[12] ++set_location_assignment PIN_B19 -to GPIO_0[13] ++set_location_assignment PIN_A20 -to GPIO_0[14] ++set_location_assignment PIN_B20 -to GPIO_0[15] ++set_location_assignment PIN_C21 -to GPIO_0[16] ++set_location_assignment PIN_C22 -to GPIO_0[17] ++set_location_assignment PIN_D21 -to GPIO_0[18] ++set_location_assignment PIN_D22 -to GPIO_0[19] ++set_location_assignment PIN_E21 -to GPIO_0[20] ++set_location_assignment PIN_E22 -to GPIO_0[21] ++set_location_assignment PIN_F21 -to GPIO_0[22] ++set_location_assignment PIN_F22 -to GPIO_0[23] ++set_location_assignment PIN_G21 -to GPIO_0[24] ++set_location_assignment PIN_G22 -to GPIO_0[25] ++set_location_assignment PIN_J21 -to GPIO_0[26] ++set_location_assignment PIN_J22 -to GPIO_0[27] ++set_location_assignment PIN_K21 -to GPIO_0[28] ++set_location_assignment PIN_K22 -to GPIO_0[29] ++set_location_assignment PIN_J19 -to GPIO_0[30] ++set_location_assignment PIN_J20 -to GPIO_0[31] ++set_location_assignment PIN_J18 -to GPIO_0[32] ++set_location_assignment PIN_K20 -to GPIO_0[33] ++set_location_assignment PIN_L19 -to GPIO_0[34] ++set_location_assignment PIN_L18 -to GPIO_0[35] ++set_location_assignment PIN_H12 -to GPIO_1[0] ++set_location_assignment PIN_H13 -to GPIO_1[1] ++set_location_assignment PIN_H14 -to GPIO_1[2] ++set_location_assignment PIN_G15 -to GPIO_1[3] ++set_location_assignment PIN_E14 -to GPIO_1[4] ++set_location_assignment PIN_E15 -to GPIO_1[5] ++set_location_assignment PIN_F15 -to GPIO_1[6] ++set_location_assignment PIN_G16 -to GPIO_1[7] ++set_location_assignment PIN_F12 -to GPIO_1[8] ++set_location_assignment PIN_F13 -to GPIO_1[9] ++set_location_assignment PIN_C14 -to GPIO_1[10] ++set_location_assignment PIN_D14 -to GPIO_1[11] ++set_location_assignment PIN_D15 -to GPIO_1[12] ++set_location_assignment PIN_D16 -to GPIO_1[13] ++set_location_assignment PIN_C17 -to GPIO_1[14] ++set_location_assignment PIN_C18 -to GPIO_1[15] ++set_location_assignment PIN_C19 -to GPIO_1[16] ++set_location_assignment PIN_C20 -to GPIO_1[17] ++set_location_assignment PIN_D19 -to GPIO_1[18] ++set_location_assignment PIN_D20 -to GPIO_1[19] ++set_location_assignment PIN_E20 -to GPIO_1[20] ++set_location_assignment PIN_F20 -to GPIO_1[21] ++set_location_assignment PIN_E19 -to GPIO_1[22] ++set_location_assignment PIN_E18 -to GPIO_1[23] ++set_location_assignment PIN_G20 -to GPIO_1[24] ++set_location_assignment PIN_G18 -to GPIO_1[25] ++set_location_assignment PIN_G17 -to GPIO_1[26] ++set_location_assignment PIN_H17 -to GPIO_1[27] ++set_location_assignment PIN_J15 -to GPIO_1[28] ++set_location_assignment PIN_H18 -to GPIO_1[29] ++set_location_assignment PIN_N22 -to GPIO_1[30] ++set_location_assignment PIN_N21 -to GPIO_1[31] ++set_location_assignment PIN_P15 -to GPIO_1[32] ++set_location_assignment PIN_N15 -to GPIO_1[33] ++set_location_assignment PIN_P17 -to GPIO_1[34] ++set_location_assignment PIN_P18 -to GPIO_1[35] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[7] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[8] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[9] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[10] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[11] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[12] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[13] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[14] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[15] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[16] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[17] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[18] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[19] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[20] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[21] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[22] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[23] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[24] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[25] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[26] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[27] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[28] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[29] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[30] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[31] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[32] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[33] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[34] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[35] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[7] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[8] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[9] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[10] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[11] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[12] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[13] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[14] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[15] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[16] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[17] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[18] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[19] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[20] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[21] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[22] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[23] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[24] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[25] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[26] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[27] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[28] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[29] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[30] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[31] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[32] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[33] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[34] ++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[35] ++set_location_assignment PIN_L22 -to SW[0] ++set_location_assignment PIN_L21 -to SW[1] ++set_location_assignment PIN_M22 -to SW[2] ++set_location_assignment PIN_V12 -to SW[3] ++set_location_assignment PIN_W12 -to SW[4] ++set_location_assignment PIN_U12 -to SW[5] ++set_location_assignment PIN_U11 -to SW[6] ++set_location_assignment PIN_M2 -to SW[7] ++set_location_assignment PIN_M1 -to SW[8] ++set_location_assignment PIN_L2 -to SW[9] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[7] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[8] ++set_instance_assignment -name IO_STANDARD LVTTL -to SW[9] ++set_location_assignment PIN_J2 -to HEX0[0] ++set_location_assignment PIN_J1 -to HEX0[1] ++set_location_assignment PIN_H2 -to HEX0[2] ++set_location_assignment PIN_H1 -to HEX0[3] ++set_location_assignment PIN_F2 -to HEX0[4] ++set_location_assignment PIN_F1 -to HEX0[5] ++set_location_assignment PIN_E2 -to HEX0[6] ++set_location_assignment PIN_E1 -to HEX1[0] ++set_location_assignment PIN_H6 -to HEX1[1] ++set_location_assignment PIN_H5 -to HEX1[2] ++set_location_assignment PIN_H4 -to HEX1[3] ++set_location_assignment PIN_G3 -to HEX1[4] ++set_location_assignment PIN_D2 -to HEX1[5] ++set_location_assignment PIN_D1 -to HEX1[6] ++set_location_assignment PIN_G5 -to HEX2[0] ++set_location_assignment PIN_G6 -to HEX2[1] ++set_location_assignment PIN_C2 -to HEX2[2] ++set_location_assignment PIN_C1 -to HEX2[3] ++set_location_assignment PIN_E3 -to HEX2[4] ++set_location_assignment PIN_E4 -to HEX2[5] ++set_location_assignment PIN_D3 -to HEX2[6] ++set_location_assignment PIN_F4 -to HEX3[0] ++set_location_assignment PIN_D5 -to HEX3[1] ++set_location_assignment PIN_D6 -to HEX3[2] ++set_location_assignment PIN_J4 -to HEX3[3] ++set_location_assignment PIN_L8 -to HEX3[4] ++set_location_assignment PIN_F3 -to HEX3[5] ++set_location_assignment PIN_D4 -to HEX3[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[6] ++set_location_assignment PIN_R22 -to KEY[0] ++set_location_assignment PIN_R21 -to KEY[1] ++set_location_assignment PIN_T22 -to KEY[2] ++set_location_assignment PIN_T21 -to KEY[3] ++set_location_assignment PIN_R20 -to LEDR[0] ++set_location_assignment PIN_R19 -to LEDR[1] ++set_location_assignment PIN_U19 -to LEDR[2] ++set_location_assignment PIN_Y19 -to LEDR[3] ++set_location_assignment PIN_T18 -to LEDR[4] ++set_location_assignment PIN_V19 -to LEDR[5] ++set_location_assignment PIN_Y18 -to LEDR[6] ++set_location_assignment PIN_U18 -to LEDR[7] ++set_location_assignment PIN_R18 -to LEDR[8] ++set_location_assignment PIN_R17 -to LEDR[9] ++set_location_assignment PIN_U22 -to LEDG[0] ++set_location_assignment PIN_U21 -to LEDG[1] ++set_location_assignment PIN_V22 -to LEDG[2] ++set_location_assignment PIN_V21 -to LEDG[3] ++set_location_assignment PIN_W22 -to LEDG[4] ++set_location_assignment PIN_W21 -to LEDG[5] ++set_location_assignment PIN_Y22 -to LEDG[6] ++set_location_assignment PIN_Y21 -to LEDG[7] ++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[7] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[8] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[9] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[4] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[5] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[6] ++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[7] ++set_location_assignment PIN_D12 -to CLOCK_27[0] ++set_location_assignment PIN_E12 -to CLOCK_27[1] ++set_location_assignment PIN_B12 -to CLOCK_24[0] ++set_location_assignment PIN_A12 -to CLOCK_24[1] ++set_location_assignment PIN_L1 -to CLOCK_50 ++set_location_assignment PIN_M21 -to EXT_CLOCK ++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_27[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_50 ++set_instance_assignment -name IO_STANDARD LVTTL -to EXT_CLOCK ++set_location_assignment PIN_H15 -to PS2_CLK ++set_location_assignment PIN_J14 -to PS2_DAT ++set_location_assignment PIN_F14 -to UART_RXD ++set_location_assignment PIN_G12 -to UART_TXD ++set_instance_assignment -name IO_STANDARD LVTTL -to PS2_CLK ++set_instance_assignment -name IO_STANDARD LVTTL -to PS2_DAT ++set_instance_assignment -name IO_STANDARD LVTTL -to UART_RXD ++set_instance_assignment -name IO_STANDARD LVTTL -to UART_TXD ++set_location_assignment PIN_E8 -to TDI ++set_location_assignment PIN_D8 -to TCS ++set_location_assignment PIN_C7 -to TCK ++set_location_assignment PIN_D7 -to TDO ++set_instance_assignment -name IO_STANDARD LVTTL -to TDI ++set_instance_assignment -name IO_STANDARD LVTTL -to TCS ++set_instance_assignment -name IO_STANDARD LVTTL -to TCK ++set_instance_assignment -name IO_STANDARD LVTTL -to TDO ++set_location_assignment PIN_D9 -to VGA_R[0] ++set_location_assignment PIN_C9 -to VGA_R[1] ++set_location_assignment PIN_A7 -to VGA_R[2] ++set_location_assignment PIN_B7 -to VGA_R[3] ++set_location_assignment PIN_B8 -to VGA_G[0] ++set_location_assignment PIN_C10 -to VGA_G[1] ++set_location_assignment PIN_B9 -to VGA_G[2] ++set_location_assignment PIN_A8 -to VGA_G[3] ++set_location_assignment PIN_A9 -to VGA_B[0] ++set_location_assignment PIN_D11 -to VGA_B[1] ++set_location_assignment PIN_A10 -to VGA_B[2] ++set_location_assignment PIN_B10 -to VGA_B[3] ++set_location_assignment PIN_A11 -to VGA_HS ++set_location_assignment PIN_B11 -to VGA_VS ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[0] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[1] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[2] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[3] ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_HS ++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_VS ++set_location_assignment PIN_A3 -to I2C_SCLK ++set_location_assignment PIN_B3 -to I2C_SDAT ++set_location_assignment PIN_A6 -to AUD_ADCLRCK ++set_location_assignment PIN_B6 -to AUD_ADCDAT ++set_location_assignment PIN_A5 -to AUD_DACLRCK ++set_location_assignment PIN_B5 -to AUD_DACDAT ++set_location_assignment PIN_B4 -to AUD_XCK ++set_location_assignment PIN_A4 -to AUD_BCLK ++set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SCLK ++set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SDAT ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCLRCK ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCDAT ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACLRCK ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACDAT ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_XCK ++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_BCLK ++set_location_assignment PIN_W4 -to DRAM_ADDR[0] ++set_location_assignment PIN_W5 -to DRAM_ADDR[1] ++set_location_assignment PIN_Y3 -to DRAM_ADDR[2] ++set_location_assignment PIN_Y4 -to DRAM_ADDR[3] ++set_location_assignment PIN_R6 -to DRAM_ADDR[4] ++set_location_assignment PIN_R5 -to DRAM_ADDR[5] ++set_location_assignment PIN_P6 -to DRAM_ADDR[6] ++set_location_assignment PIN_P5 -to DRAM_ADDR[7] ++set_location_assignment PIN_P3 -to DRAM_ADDR[8] ++set_location_assignment PIN_N4 -to DRAM_ADDR[9] ++set_location_assignment PIN_W3 -to DRAM_ADDR[10] ++set_location_assignment PIN_N6 -to DRAM_ADDR[11] ++set_location_assignment PIN_U3 -to DRAM_BA_0 ++set_location_assignment PIN_V4 -to DRAM_BA_1 ++set_location_assignment PIN_T3 -to DRAM_CAS_N ++set_location_assignment PIN_N3 -to DRAM_CKE ++set_location_assignment PIN_U4 -to DRAM_CLK ++set_location_assignment PIN_T6 -to DRAM_CS_N ++set_location_assignment PIN_U1 -to DRAM_DQ[0] ++set_location_assignment PIN_U2 -to DRAM_DQ[1] ++set_location_assignment PIN_V1 -to DRAM_DQ[2] ++set_location_assignment PIN_V2 -to DRAM_DQ[3] ++set_location_assignment PIN_W1 -to DRAM_DQ[4] ++set_location_assignment PIN_W2 -to DRAM_DQ[5] ++set_location_assignment PIN_Y1 -to DRAM_DQ[6] ++set_location_assignment PIN_Y2 -to DRAM_DQ[7] ++set_location_assignment PIN_N1 -to DRAM_DQ[8] ++set_location_assignment PIN_N2 -to DRAM_DQ[9] ++set_location_assignment PIN_P1 -to DRAM_DQ[10] ++set_location_assignment PIN_P2 -to DRAM_DQ[11] ++set_location_assignment PIN_R1 -to DRAM_DQ[12] ++set_location_assignment PIN_R2 -to DRAM_DQ[13] ++set_location_assignment PIN_T1 -to DRAM_DQ[14] ++set_location_assignment PIN_T2 -to DRAM_DQ[15] ++set_location_assignment PIN_R7 -to DRAM_LDQM ++set_location_assignment PIN_T5 -to DRAM_RAS_N ++set_location_assignment PIN_M5 -to DRAM_UDQM ++set_location_assignment PIN_R8 -to DRAM_WE_N ++set_location_assignment PIN_AB20 -to FL_ADDR[0] ++set_location_assignment PIN_AA14 -to FL_ADDR[1] ++set_location_assignment PIN_Y16 -to FL_ADDR[2] ++set_location_assignment PIN_R15 -to FL_ADDR[3] ++set_location_assignment PIN_T15 -to FL_ADDR[4] ++set_location_assignment PIN_U15 -to FL_ADDR[5] ++set_location_assignment PIN_V15 -to FL_ADDR[6] ++set_location_assignment PIN_W15 -to FL_ADDR[7] ++set_location_assignment PIN_R14 -to FL_ADDR[8] ++set_location_assignment PIN_Y13 -to FL_ADDR[9] ++set_location_assignment PIN_R12 -to FL_ADDR[10] ++set_location_assignment PIN_T12 -to FL_ADDR[11] ++set_location_assignment PIN_AB14 -to FL_ADDR[12] ++set_location_assignment PIN_AA13 -to FL_ADDR[13] ++set_location_assignment PIN_AB13 -to FL_ADDR[14] ++set_location_assignment PIN_AA12 -to FL_ADDR[15] ++set_location_assignment PIN_AB12 -to FL_ADDR[16] ++set_location_assignment PIN_AA20 -to FL_ADDR[17] ++set_location_assignment PIN_U14 -to FL_ADDR[18] ++set_location_assignment PIN_V14 -to FL_ADDR[19] ++set_location_assignment PIN_U13 -to FL_ADDR[20] ++set_location_assignment PIN_R13 -to FL_ADDR[21] ++set_location_assignment PIN_AB16 -to FL_DQ[0] ++set_location_assignment PIN_AA16 -to FL_DQ[1] ++set_location_assignment PIN_AB17 -to FL_DQ[2] ++set_location_assignment PIN_AA17 -to FL_DQ[3] ++set_location_assignment PIN_AB18 -to FL_DQ[4] ++set_location_assignment PIN_AA18 -to FL_DQ[5] ++set_location_assignment PIN_AB19 -to FL_DQ[6] ++set_location_assignment PIN_AA19 -to FL_DQ[7] ++set_location_assignment PIN_AA15 -to FL_OE_N ++set_location_assignment PIN_W14 -to FL_RST_N ++set_location_assignment PIN_Y14 -to FL_WE_N ++set_location_assignment PIN_AA3 -to SRAM_ADDR[0] ++set_location_assignment PIN_AB3 -to SRAM_ADDR[1] ++set_location_assignment PIN_AA4 -to SRAM_ADDR[2] ++set_location_assignment PIN_AB4 -to SRAM_ADDR[3] ++set_location_assignment PIN_AA5 -to SRAM_ADDR[4] ++set_location_assignment PIN_AB10 -to SRAM_ADDR[5] ++set_location_assignment PIN_AA11 -to SRAM_ADDR[6] ++set_location_assignment PIN_AB11 -to SRAM_ADDR[7] ++set_location_assignment PIN_V11 -to SRAM_ADDR[8] ++set_location_assignment PIN_W11 -to SRAM_ADDR[9] ++set_location_assignment PIN_R11 -to SRAM_ADDR[10] ++set_location_assignment PIN_T11 -to SRAM_ADDR[11] ++set_location_assignment PIN_Y10 -to SRAM_ADDR[12] ++set_location_assignment PIN_U10 -to SRAM_ADDR[13] ++set_location_assignment PIN_R10 -to SRAM_ADDR[14] ++set_location_assignment PIN_T7 -to SRAM_ADDR[15] ++set_location_assignment PIN_Y6 -to SRAM_ADDR[16] ++set_location_assignment PIN_Y5 -to SRAM_ADDR[17] ++set_location_assignment PIN_AB5 -to SRAM_CE_N ++set_location_assignment PIN_AA6 -to SRAM_DQ[0] ++set_location_assignment PIN_AB6 -to SRAM_DQ[1] ++set_location_assignment PIN_AA7 -to SRAM_DQ[2] ++set_location_assignment PIN_AB7 -to SRAM_DQ[3] ++set_location_assignment PIN_AA8 -to SRAM_DQ[4] ++set_location_assignment PIN_AB8 -to SRAM_DQ[5] ++set_location_assignment PIN_AA9 -to SRAM_DQ[6] ++set_location_assignment PIN_AB9 -to SRAM_DQ[7] ++set_location_assignment PIN_Y9 -to SRAM_DQ[8] ++set_location_assignment PIN_W9 -to SRAM_DQ[9] ++set_location_assignment PIN_V9 -to SRAM_DQ[10] ++set_location_assignment PIN_U9 -to SRAM_DQ[11] ++set_location_assignment PIN_R9 -to SRAM_DQ[12] ++set_location_assignment PIN_W8 -to SRAM_DQ[13] ++set_location_assignment PIN_V8 -to SRAM_DQ[14] ++set_location_assignment PIN_U8 -to SRAM_DQ[15] ++set_location_assignment PIN_Y7 -to SRAM_LB_N ++set_location_assignment PIN_T8 -to SRAM_OE_N ++set_location_assignment PIN_W7 -to SRAM_UB_N ++set_location_assignment PIN_AA10 -to SRAM_WE_N ++set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED WITH WEAK PULL-UP" ++set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top ++set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top ++set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region" ++set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region" ++set_global_assignment -name MISC_FILE "U:/git_repos/fpga/bbc/bbc_micro_de1.dpf" ++set_location_assignment PIN_AB15 -to FL_CE_N ++set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" ++set_global_assignment -name STRATIX_CONFIGURATION_DEVICE EPCS4 ++set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED" ++set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" ++set_location_assignment PIN_U20 -to SD_nCS ++set_location_assignment PIN_V20 -to SD_SCLK ++set_location_assignment PIN_Y20 -to SD_MOSI ++set_location_assignment PIN_W20 -to SD_MISO ++set_global_assignment -name VHDL_FILE saa5050.vhd ++set_global_assignment -name VHDL_FILE i2s_intf.vhd ++set_global_assignment -name VHDL_FILE i2c_loader.vhd ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_comp_pack-p.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_noise.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_tone.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_top.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_attenuator.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_clock_div.vhd" ++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_latch_ctrl.vhd" ++set_global_assignment -name VHDL_FILE ps2_intf.vhd ++set_global_assignment -name VHDL_FILE m6522.vhd ++set_global_assignment -name VHDL_FILE seg7.vhd ++set_global_assignment -name VHDL_FILE vidproc.vhd ++set_global_assignment -name VHDL_FILE mc6845.vhd ++set_global_assignment -name VHDL_FILE T65/T65_Pack.vhd ++set_global_assignment -name VHDL_FILE T65/T65.vhd ++set_global_assignment -name VHDL_FILE T65/T65_ALU.vhd ++set_global_assignment -name VHDL_FILE T65/T65_MCode.vhd ++set_global_assignment -name QIP_FILE pll32.qip ++set_global_assignment -name VHDL_FILE bbc_micro_de1.vhd ++set_global_assignment -name VHDL_FILE bbc_micro_de1_tb.vhd ++set_global_assignment -name VHDL_FILE m6522_tb.vhd ++set_global_assignment -name VHDL_FILE keyboard.vhd ++set_global_assignment -name VHDL_FILE debugger.vhd ++set_global_assignment -name QIP_FILE saa5050_rom.qip + set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top +\ No newline at end of file +diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd +index e109c36..0fca9de 100644 +--- a/bbc_micro_de1.vhd ++++ b/bbc_micro_de1.vhd +@@ -1,1265 +1,1265 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC B Micro
+---
+--- Terasic DE1 top-level
+---
+--- (C) 2011 Mike Stirling
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+--- Generic top-level entity for Altera DE1 board
+-entity bbc_micro_de1 is
+-generic (
+- -- ROM offset
+- -- The 4MB Flash is used in 16KB banks as a simple mechanism for
+- -- different machines to address different parts of the ROM, saving
+- -- on re-flashing each time a new machine is run on the board.
+- -- This generic sets the upper 8 address bits.
+- -- Note that the lower bits may be ignored by the implementation,
+- -- e.g. where ROMs are bigger than 16K or where multiple banks
+- -- are required. In this case it is important to ensure that the
+- -- ROM images are aligned correctly (such that these ignored bits are 0).
+- --
+- -- For the BBC the ROMs start in bank 8 (the first 8 banks are used by
+- -- the Spectrum project). The particular bank is selected by the sideways
+- -- ROM paging register, and bank 7 is used for the MOS. Recommended layout
+- -- is:
+- --
+- -- 0 Sideways
+- -- 1 Sideways
+- -- 2 Sideways - SuperMMC (DFS)
+- -- 3 Sideways - BASIC
+- -- 4 Not used
+- -- 5 Not used
+- -- 6 Not used
+- -- 7 MOS
+- ROM_OFFSET : std_logic_vector(7 downto 0) := "00001000"
+- );
+-port (
+- -- Clocks
+- CLOCK_24 : in std_logic_vector(1 downto 0);
+- CLOCK_27 : in std_logic_vector(1 downto 0);
+- CLOCK_50 : in std_logic;
+- EXT_CLOCK : in std_logic;
+-
+- -- Switches
+- SW : in std_logic_vector(9 downto 0);
+- -- Buttons
+- KEY : in std_logic_vector(3 downto 0);
+-
+- -- 7 segment displays
+- HEX0 : out std_logic_vector(6 downto 0);
+- HEX1 : out std_logic_vector(6 downto 0);
+- HEX2 : out std_logic_vector(6 downto 0);
+- HEX3 : out std_logic_vector(6 downto 0);
+- -- Red LEDs
+- LEDR : out std_logic_vector(9 downto 0);
+- -- Green LEDs
+- LEDG : out std_logic_vector(7 downto 0);
+-
+- -- VGA
+- VGA_R : out std_logic_vector(3 downto 0);
+- VGA_G : out std_logic_vector(3 downto 0);
+- VGA_B : out std_logic_vector(3 downto 0);
+- VGA_HS : out std_logic;
+- VGA_VS : out std_logic;
+-
+- -- Serial
+- UART_RXD : in std_logic;
+- UART_TXD : out std_logic;
+-
+- -- PS/2 Keyboard
+- PS2_CLK : inout std_logic;
+- PS2_DAT : inout std_logic;
+-
+- -- I2C
+- I2C_SCLK : inout std_logic;
+- I2C_SDAT : inout std_logic;
+-
+- -- Audio
+- AUD_XCK : out std_logic;
+- AUD_BCLK : out std_logic;
+- AUD_ADCLRCK : out std_logic;
+- AUD_ADCDAT : in std_logic;
+- AUD_DACLRCK : out std_logic;
+- AUD_DACDAT : out std_logic;
+-
+- -- SRAM
+- SRAM_ADDR : out std_logic_vector(17 downto 0);
+- SRAM_DQ : inout std_logic_vector(15 downto 0);
+- SRAM_CE_N : out std_logic;
+- SRAM_OE_N : out std_logic;
+- SRAM_WE_N : out std_logic;
+- SRAM_UB_N : out std_logic;
+- SRAM_LB_N : out std_logic;
+-
+- -- SDRAM
+- DRAM_ADDR : out std_logic_vector(11 downto 0);
+- DRAM_DQ : inout std_logic_vector(15 downto 0);
+- DRAM_BA_0 : in std_logic;
+- DRAM_BA_1 : in std_logic;
+- DRAM_CAS_N : in std_logic;
+- DRAM_CKE : in std_logic;
+- DRAM_CLK : in std_logic;
+- DRAM_CS_N : in std_logic;
+- DRAM_LDQM : in std_logic;
+- DRAM_RAS_N : in std_logic;
+- DRAM_UDQM : in std_logic;
+- DRAM_WE_N : in std_logic;
+-
+- -- Flash
+- FL_ADDR : out std_logic_vector(21 downto 0);
+- FL_DQ : inout std_logic_vector(7 downto 0);
+- FL_RST_N : out std_logic;
+- FL_OE_N : out std_logic;
+- FL_WE_N : out std_logic;
+- FL_CE_N : out std_logic;
+-
+- -- SD card (SPI mode)
+- SD_nCS : out std_logic;
+- SD_MOSI : out std_logic;
+- SD_SCLK : out std_logic;
+- SD_MISO : in std_logic;
+-
+- -- GPIO
+- GPIO_0 : inout std_logic_vector(35 downto 0);
+- GPIO_1 : inout std_logic_vector(35 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of bbc_micro_de1 is
+-
+-------------------------------
+--- PLL (32 MHz master clock)
+-------------------------------
+-
+-component pll32 IS
+- PORT
+- (
+- areset : IN STD_LOGIC := '0';
+- inclk0 : IN STD_LOGIC := '0';
+- c0 : OUT STD_LOGIC ;
+- locked : OUT STD_LOGIC
+- );
+-end component;
+-
+----------
+--- CPU
+----------
+-
+-component T65 is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Res_n : in std_logic;
+- Enable : in std_logic;
+- Clk : in std_logic;
+- Rdy : in std_logic;
+- Abort_n : in std_logic;
+- IRQ_n : in std_logic;
+- NMI_n : in std_logic;
+- SO_n : in std_logic;
+- R_W_n : out std_logic;
+- Sync : out std_logic;
+- EF : out std_logic;
+- MF : out std_logic;
+- XF : out std_logic;
+- ML_n : out std_logic;
+- VP_n : out std_logic;
+- VDA : out std_logic;
+- VPA : out std_logic;
+- A : out std_logic_vector(23 downto 0);
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0)
+- );
+-end component;
+-
+------------------
+--- MC6845 CRTC
+------------------
+-
+-component mc6845 is
+-port (
+- CLOCK : in std_logic;
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- R_nW : in std_logic;
+- RS : in std_logic;
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0);
+-
+- -- Display interface
+- VSYNC : out std_logic;
+- HSYNC : out std_logic;
+- DE : out std_logic;
+- CURSOR : out std_logic;
+- LPSTB : in std_logic;
+-
+- -- Memory interface
+- MA : out std_logic_vector(13 downto 0);
+- RA : out std_logic_vector(4 downto 0)
+- );
+-end component;
+-
+--------------------------
+--- "VIDPROC" Video ULA
+--------------------------
+-
+-component vidproc is
+-port (
+- CLOCK : in std_logic;
+- -- Clock enable qualifies display cycles (interleaved with CPU cycles)
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Clock enable output to CRTC
+- CLKEN_CRTC : out std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- A0 : in std_logic;
+- -- CPU data bus (for register writes)
+- DI_CPU : in std_logic_vector(7 downto 0);
+- -- Display RAM data bus (for display data fetch)
+- DI_RAM : in std_logic_vector(7 downto 0);
+-
+- -- Control interface
+- nINVERT : in std_logic;
+- DISEN : in std_logic;
+- CURSOR : in std_logic;
+-
+- -- Video in (teletext mode)
+- R_IN : in std_logic;
+- G_IN : in std_logic;
+- B_IN : in std_logic;
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic
+- );
+-end component;
+-
+---------------------------------
+--- SAA5050 Teletext Generator
+---------------------------------
+-
+-component saa5050 is
+-port (
+- CLOCK : in std_logic;
+- -- 6 MHz dot clock enable
+- CLKEN : in std_logic;
+- -- Async reset
+- nRESET : in std_logic;
+-
+- -- Character data input (in the bus clock domain)
+- DI_CLOCK : in std_logic;
+- DI_CLKEN : in std_logic;
+- DI : in std_logic_vector(6 downto 0);
+-
+- -- Timing inputs
+- -- General line reset (not used)
+- GLR : in std_logic; -- /HSYNC
+- -- Data entry window - high during VSYNC.
+- -- Resets ROM row counter and drives 'flash' signal
+- DEW : in std_logic; -- VSYNC
+- -- Character rounding select - high during even field
+- CRS : in std_logic; -- FIELD
+- -- Load output shift register enable - high during active video
+- LOSE : in std_logic; -- DE
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic;
+- Y : out std_logic
+- );
+-end component;
+-
+---------------
+--- 6522 VIA
+---------------
+-
+-component M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- FIXME: Revisit timing in this component. Does it really need a 4x clock?
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable (4x system clock rate)
+- CLK : in std_logic
+- );
+-end component;
+-
+------------------------------
+--- PS/2 Keyboard Emulation
+------------------------------
+-
+-component keyboard is
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- CLKEN_1MHZ : in std_logic;
+-
+- -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- If 1 then column is incremented automatically at
+- -- 1 MHz rate
+- AUTOSCAN : in std_logic;
+-
+- COLUMN : in std_logic_vector(3 downto 0);
+- ROW : in std_logic_vector(2 downto 0);
+-
+- -- 1 when currently selected key is down (AUTOSCAN disabled)
+- KEYPRESS : out std_logic;
+- -- 1 when any key is down (except row 0)
+- INT : out std_logic;
+- -- BREAK key output - 1 when pressed
+- BREAK_OUT : out std_logic;
+-
+- -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
+- );
+-end component;
+-
+------------------------------
+--- SN76489 sound generator
+------------------------------
+-
+-component sn76489_top is
+-
+- generic (
+- clock_div_16_g : integer := 1
+- );
+- port (
+- clock_i : in std_logic;
+- clock_en_i : in std_logic;
+- res_n_i : in std_logic;
+- ce_n_i : in std_logic;
+- we_n_i : in std_logic;
+- ready_o : out std_logic;
+- d_i : in std_logic_vector(0 to 7);
+- aout_o : out signed(0 to 7)
+- );
+-
+-end component;
+-
+-component i2s_intf is
+-generic(
+- mclk_rate : positive := 12000000;
+- sample_rate : positive := 8000;
+- preamble : positive := 1; -- I2S
+- word_length : positive := 16
+- );
+-
+-port (
+- -- 2x MCLK in (e.g. 24 MHz for WM8731 USB mode)
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Parallel IO
+- PCM_INL : out std_logic_vector(word_length - 1 downto 0);
+- PCM_INR : out std_logic_vector(word_length - 1 downto 0);
+- PCM_OUTL : in std_logic_vector(word_length - 1 downto 0);
+- PCM_OUTR : in std_logic_vector(word_length - 1 downto 0);
+-
+- -- Codec interface (right justified mode)
+- -- MCLK is generated at half of the CLK input
+- I2S_MCLK : out std_logic;
+- -- LRCLK is equal to the sample rate and is synchronous to
+- -- MCLK. It must be related to MCLK by the oversampling ratio
+- -- given in the codec datasheet.
+- I2S_LRCLK : out std_logic;
+-
+- -- Data is shifted out on the falling edge of BCLK, sampled
+- -- on the rising edge. The bit rate is determined such that
+- -- it is fast enough to fit preamble + word_length bits into
+- -- each LRCLK half cycle. The last cycle of each word may be
+- -- stretched to fit to LRCLK. This is OK at least for the
+- -- WM8731 codec.
+- -- The first falling edge of each timeslot is always synchronised
+- -- with the LRCLK edge.
+- I2S_BCLK : out std_logic;
+- -- Output bitstream
+- I2S_DOUT : out std_logic;
+- -- Input bitstream
+- I2S_DIN : in std_logic
+- );
+-end component;
+-
+-component i2c_loader is
+-generic (
+- -- Address of slave to be loaded
+- device_address : integer := 16#1a#;
+- -- Number of retries to allow before stopping
+- num_retries : integer := 0;
+- -- Length of clock divider in bits. Resulting bus frequency is
+- -- CLK/2^(log2_divider + 2)
+- log2_divider : integer := 6
+-);
+-
+-port (
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- I2C_SCL : inout std_logic;
+- I2C_SDA : inout std_logic;
+-
+- IS_DONE : out std_logic;
+- IS_ERROR : out std_logic
+- );
+-end component;
+-
+-component debugger is
+-generic (
+- -- Set this for a reasonable half flash duration relative to the
+- -- clock frequency
+- flash_divider : natural := 24
+- );
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- -- CPU clock enable in
+- CLKEN_IN : in std_logic;
+- -- Gated clock enable back out to CPU
+- CLKEN_OUT : out std_logic;
+- -- CPU IRQ in
+- nIRQ_IN : in std_logic;
+- -- Gated IRQ back out to CPU (no interrupts when single stepping)
+- nIRQ_OUT : out std_logic;
+-
+- -- CPU
+- A_CPU : in std_logic_vector(15 downto 0);
+- R_nW : in std_logic;
+- SYNC : in std_logic;
+-
+- -- Aux bus input for display in hex
+- AUX_BUS : in std_logic_vector(15 downto 0);
+-
+- -- Controls
+- -- RUN or HALT CPU
+- RUN : in std_logic;
+- -- Push button to single-step in HALT mode
+- nSTEP : in std_logic;
+- -- Push button to cycle display mode
+- nMODE : in std_logic;
+- -- Push button to cycle display digit in edit mode
+- nDIGIT : in std_logic;
+- -- Push button to cycle digit value in edit mode
+- nSET : in std_logic;
+-
+- -- Output to display
+- DIGIT3 : out std_logic_vector(6 downto 0);
+- DIGIT2 : out std_logic_vector(6 downto 0);
+- DIGIT1 : out std_logic_vector(6 downto 0);
+- DIGIT0 : out std_logic_vector(6 downto 0);
+-
+- LED_BREAKPOINT : out std_logic;
+- LED_WATCHPOINT : out std_logic
+- );
+-end component;
+-
+--------------
+--- Signals
+--------------
+-
+--- Master clock - 32 MHz
+-signal pll_reset : std_logic;
+-signal pll_locked : std_logic;
+-signal clock : std_logic;
+-signal hard_reset_n : std_logic;
+-signal reset_n : std_logic;
+-
+--- Clock enable counter
+--- CPU and video cycles are interleaved. The CPU runs at 2 MHz (every 16th
+--- cycle) and the video subsystem is enabled on every odd cycle.
+-signal clken_counter : unsigned(4 downto 0);
+-signal cpu_cycle : std_logic; -- Qualifies all 2 MHz cycles
+-signal cpu_cycle_mask : std_logic; -- Set to mask CPU cycles until 1 MHz cycle is complete
+-signal cpu_clken : std_logic; -- 2 MHz cycles in which the CPU is enabled
+-signal cpu_debug_clken : std_logic; -- CPU clken return from hardware debugger
+--- IO cycles are out of phase with the CPU
+-signal vid_clken : std_logic; -- 16 MHz video cycles
+-signal mhz4_clken : std_logic; -- Used by 6522
+-signal mhz2_clken : std_logic; -- Used for latching CPU address for clock stretch
+-signal mhz1_clken : std_logic; -- 1 MHz bus and associated peripherals, 6522 phase 2
+--- SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock
+-signal ttxt_clken_counter : unsigned(1 downto 0);
+-signal ttxt_clken : std_logic;
+-
+--- Debugger connections
+-signal debug_irq_in_n : std_logic;
+-signal debug_aux : std_logic_vector(15 downto 0);
+-
+--- CPU signals
+-signal cpu_mode : std_logic_vector(1 downto 0);
+-signal cpu_ready : std_logic;
+-signal cpu_abort_n : std_logic;
+-signal cpu_irq_n : std_logic;
+-signal cpu_nmi_n : std_logic;
+-signal cpu_so_n : std_logic;
+-signal cpu_r_nw : std_logic;
+-signal cpu_sync : std_logic;
+-signal cpu_ef : std_logic;
+-signal cpu_mf : std_logic;
+-signal cpu_xf : std_logic;
+-signal cpu_ml_n : std_logic;
+-signal cpu_vp_n : std_logic;
+-signal cpu_vda : std_logic;
+-signal cpu_vpa : std_logic;
+-signal cpu_a : std_logic_vector(23 downto 0);
+-signal cpu_di : std_logic_vector(7 downto 0);
+-signal cpu_do : std_logic_vector(7 downto 0);
+-
+--- CRTC signals
+-signal crtc_clken : std_logic;
+-signal crtc_do : std_logic_vector(7 downto 0);
+-signal crtc_vsync : std_logic;
+-signal crtc_hsync : std_logic;
+-signal crtc_de : std_logic;
+-signal crtc_cursor : std_logic;
+-signal crtc_lpstb : std_logic := '0';
+-signal crtc_ma : std_logic_vector(13 downto 0);
+-signal crtc_ra : std_logic_vector(4 downto 0);
+-
+--- Decoded display address after address translation for hardware
+--- scrolling
+-signal display_a : std_logic_vector(14 downto 0);
+-
+--- "VIDPROC" signals
+-signal vidproc_invert_n : std_logic;
+-signal vidproc_disen : std_logic;
+-signal r_in : std_logic;
+-signal g_in : std_logic;
+-signal b_in : std_logic;
+-signal r_out : std_logic;
+-signal g_out : std_logic;
+-signal b_out : std_logic;
+-
+--- SAA5050 signals
+-signal ttxt_glr : std_logic;
+-signal ttxt_dew : std_logic;
+-signal ttxt_crs : std_logic;
+-signal ttxt_lose : std_logic;
+-signal ttxt_r : std_logic;
+-signal ttxt_g : std_logic;
+-signal ttxt_b : std_logic;
+-signal ttxt_y : std_logic;
+-
+--- System VIA signals
+-signal sys_via_do : std_logic_vector(7 downto 0);
+-signal sys_via_do_oe_n : std_logic;
+-signal sys_via_irq_n : std_logic;
+-signal sys_via_ca1_in : std_logic := '0';
+-signal sys_via_ca2_in : std_logic := '0';
+-signal sys_via_ca2_out : std_logic;
+-signal sys_via_ca2_oe_n : std_logic;
+-signal sys_via_pa_in : std_logic_vector(7 downto 0);
+-signal sys_via_pa_out : std_logic_vector(7 downto 0);
+-signal sys_via_pa_oe_n : std_logic_vector(7 downto 0);
+-signal sys_via_cb1_in : std_logic := '0';
+-signal sys_via_cb1_out : std_logic;
+-signal sys_via_cb1_oe_n : std_logic;
+-signal sys_via_cb2_in : std_logic := '0';
+-signal sys_via_cb2_out : std_logic;
+-signal sys_via_cb2_oe_n : std_logic;
+-signal sys_via_pb_in : std_logic_vector(7 downto 0);
+-signal sys_via_pb_out : std_logic_vector(7 downto 0);
+-signal sys_via_pb_oe_n : std_logic_vector(7 downto 0);
+-
+--- User VIA signals
+-signal user_via_do : std_logic_vector(7 downto 0);
+-signal user_via_do_oe_n : std_logic;
+-signal user_via_irq_n : std_logic;
+-signal user_via_ca1_in : std_logic := '0';
+-signal user_via_ca2_in : std_logic := '0';
+-signal user_via_ca2_out : std_logic;
+-signal user_via_ca2_oe_n : std_logic;
+-signal user_via_pa_in : std_logic_vector(7 downto 0);
+-signal user_via_pa_out : std_logic_vector(7 downto 0);
+-signal user_via_pa_oe_n : std_logic_vector(7 downto 0);
+-signal user_via_cb1_in : std_logic := '0';
+-signal user_via_cb1_out : std_logic;
+-signal user_via_cb1_oe_n : std_logic;
+-signal user_via_cb2_in : std_logic := '0';
+-signal user_via_cb2_out : std_logic;
+-signal user_via_cb2_oe_n : std_logic;
+-signal user_via_pb_in : std_logic_vector(7 downto 0);
+-signal user_via_pb_out : std_logic_vector(7 downto 0);
+-signal user_via_pb_oe_n : std_logic_vector(7 downto 0);
+-
+--- IC32 latch on System VIA
+-signal ic32 : std_logic_vector(7 downto 0);
+-signal sound_enable_n : std_logic;
+-signal speech_read_n : std_logic;
+-signal speech_write_n : std_logic;
+-signal keyb_enable_n : std_logic;
+-signal disp_addr_offs : std_logic_vector(1 downto 0);
+-signal caps_lock_led_n : std_logic;
+-signal shift_lock_led_n : std_logic;
+-
+--- Keyboard
+-signal keyb_column : std_logic_vector(3 downto 0);
+-signal keyb_row : std_logic_vector(2 downto 0);
+-signal keyb_out : std_logic;
+-signal keyb_int : std_logic;
+-signal keyb_break : std_logic;
+-
+--- Sound generator
+-signal sound_ready : std_logic;
+-signal sound_di : std_logic_vector(7 downto 0);
+-signal sound_ao : signed(7 downto 0);
+-signal pcm_inl : std_logic_vector(15 downto 0);
+-signal pcm_inr : std_logic_vector(15 downto 0);
+-
+--- Memory enables
+-signal ram_enable : std_logic; -- 0x0000
+-signal rom_enable : std_logic; -- 0x8000 (BASIC/sideways ROMs)
+-signal mos_enable : std_logic; -- 0xC000
+--- IO region enables
+-signal io_fred : std_logic; -- 0xFC00 (1 MHz bus)
+-signal io_jim : std_logic; -- 0xFD00 (1 MHz bus)
+-signal io_sheila : std_logic; -- 0xFE00 (System peripherals)
+--- SHIELA
+-signal crtc_enable : std_logic; -- 0xFE00-FE07
+-signal acia_enable : std_logic; -- 0xFE08-FE0F
+-signal serproc_enable : std_logic; -- 0xFE10-FE1F
+-signal vidproc_enable : std_logic; -- 0xFE20-FE2F
+-signal romsel_enable : std_logic; -- 0xFE30-FE3F
+-signal sys_via_enable : std_logic; -- 0xFE40-FE5F
+-signal user_via_enable : std_logic; -- 0xFE60-FE7F
+-signal fddc_enable : std_logic; -- 0xFE80-FE9F
+-signal adlc_enable : std_logic; -- 0xFEA0-FEBF (Econet)
+-signal adc_enable : std_logic; -- 0xFEC0-FEDF
+-signal tube_enable : std_logic; -- 0xFEE0-FEFF
+-
+--- ROM select latch
+-signal romsel : std_logic_vector(3 downto 0);
+-
+-signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral
+-
+-begin
+- -------------------------
+- -- COMPONENT INSTANCES
+- -------------------------
+-
+- -- 32 MHz master clock
+- pll: pll32 port map (
+- pll_reset,
+- CLOCK_24(0),
+- clock,
+- pll_locked );
+-
+- -- Hardware debugger block (single-step, breakpoints)
+- debug: debugger port map (
+- clock,
+- hard_reset_n,
+- cpu_clken,
+- cpu_debug_clken,
+- debug_irq_in_n,
+- cpu_irq_n,
+- cpu_a(15 downto 0), cpu_r_nw, cpu_sync,
+- debug_aux,
+- SW(8), -- RUN
+- KEY(3), -- STEP
+- KEY(2), -- MODE
+- KEY(1), -- DIGIT
+- KEY(0), -- SET
+- HEX3, HEX2, HEX1, HEX0,
+- LEDR(3), -- BREAKPOINT
+- LEDR(2) -- WATCHPOINT
+- );
+-
+- -- 6502 CPU
+- cpu : T65 port map (
+- cpu_mode,
+- reset_n,
+- cpu_debug_clken,
+- clock,
+- cpu_ready,
+- cpu_abort_n,
+- cpu_irq_n,
+- cpu_nmi_n,
+- cpu_so_n,
+- cpu_r_nw,
+- cpu_sync,
+- cpu_ef,
+- cpu_mf,
+- cpu_xf,
+- cpu_ml_n,
+- cpu_vp_n,
+- cpu_vda,
+- cpu_vpa,
+- cpu_a,
+- cpu_di,
+- cpu_do );
+-
+- crtc : mc6845 port map (
+- clock,
+- crtc_clken,
+- reset_n,
+- crtc_enable,
+- cpu_r_nw,
+- cpu_a(0),
+- cpu_do,
+- crtc_do,
+- crtc_vsync,
+- crtc_hsync,
+- crtc_de,
+- crtc_cursor,
+- crtc_lpstb,
+- crtc_ma,
+- crtc_ra );
+-
+- video_ula : vidproc port map (
+- clock,
+- vid_clken,
+- reset_n,
+- crtc_clken,
+- vidproc_enable,
+- cpu_a(0),
+- cpu_do,
+- SRAM_DQ(7 downto 0),
+- vidproc_invert_n,
+- vidproc_disen,
+- crtc_cursor,
+- r_in, g_in, b_in,
+- r_out, g_out, b_out
+- );
+-
+- teletext : saa5050 port map (
+- CLOCK_24(0), -- This runs at 6 MHz, which we can't derive from the 32 MHz clock
+- ttxt_clken,
+- reset_n,
+- clock, -- Data input is synchronised from the bus clock domain
+- vid_clken,
+- SRAM_DQ(6 downto 0),
+- ttxt_glr,
+- ttxt_dew,
+- ttxt_crs,
+- ttxt_lose,
+- ttxt_r, ttxt_g, ttxt_b, ttxt_y
+- );
+-
+- -- System VIA
+- system_via : m6522 port map (
+- cpu_a(3 downto 0),
+- cpu_do,
+- sys_via_do,
+- sys_via_do_oe_n,
+- cpu_r_nw,
+- sys_via_enable,
+- '0', -- nCS2
+- sys_via_irq_n,
+- sys_via_ca1_in,
+- sys_via_ca2_in,
+- sys_via_ca2_out,
+- sys_via_ca2_oe_n,
+- sys_via_pa_in,
+- sys_via_pa_out,
+- sys_via_pa_oe_n,
+- sys_via_cb1_in,
+- sys_via_cb1_out,
+- sys_via_cb1_oe_n,
+- sys_via_cb2_in,
+- sys_via_cb2_out,
+- sys_via_cb2_oe_n,
+- sys_via_pb_in,
+- sys_via_pb_out,
+- sys_via_pb_oe_n,
+- mhz1_clken,
+- hard_reset_n, -- System VIA is reset by power on reset only
+- mhz4_clken,
+- clock
+- );
+-
+- -- User VIA
+- user_via : m6522 port map (
+- cpu_a(3 downto 0),
+- cpu_do,
+- user_via_do,
+- user_via_do_oe_n,
+- cpu_r_nw,
+- user_via_enable,
+- '0', -- nCS2
+- user_via_irq_n,
+- user_via_ca1_in,
+- user_via_ca2_in,
+- user_via_ca2_out,
+- user_via_ca2_oe_n,
+- user_via_pa_in,
+- user_via_pa_out,
+- user_via_pa_oe_n,
+- user_via_cb1_in,
+- user_via_cb1_out,
+- user_via_cb1_oe_n,
+- user_via_cb2_in,
+- user_via_cb2_out,
+- user_via_cb2_oe_n,
+- user_via_pb_in,
+- user_via_pb_out,
+- user_via_pb_oe_n,
+- mhz1_clken,
+- reset_n,
+- mhz4_clken,
+- clock
+- );
+-
+- -- Keyboard
+- keyb : keyboard port map (
+- clock, hard_reset_n, mhz1_clken,
+- PS2_CLK, PS2_DAT,
+- keyb_enable_n,
+- keyb_column,
+- keyb_row,
+- keyb_out,
+- keyb_int,
+- keyb_break,
+- SW(7 downto 0)
+- );
+-
+- -- Sound generator (and drive logic for I2S codec)
+- sound : sn76489_top port map (
+- clock, mhz4_clken,
+- reset_n, '0', sound_enable_n,
+- sound_ready, sound_di,
+- sound_ao
+- );
+- i2s : i2s_intf port map (
+- CLOCK_24(0), reset_n,
+- pcm_inl, pcm_inr,
+- std_logic_vector(sound_ao) & "00000000",
+- std_logic_vector(sound_ao) & "00000000",
+- AUD_XCK, AUD_DACLRCK,
+- AUD_BCLK, AUD_DACDAT, AUD_ADCDAT
+- );
+- i2c : i2c_loader
+- generic map (
+- log2_divider => 7
+- )
+- port map (
+- clock, reset_n,
+- I2C_SCLK, I2C_SDAT,
+- LEDR(5), -- IS_DONE
+- LEDR(4) -- IS_ERROR
+- );
+-
+- -- Asynchronous reset
+- -- PLL is reset by external reset switch
+- pll_reset <= not SW(9);
+- -- Keyboard and System VIA are reset by external reset switch or PLL being out of lock
+- hard_reset_n <= not (pll_reset or not pll_locked);
+- -- Rest of system is reset by all of the above plus the keyboard BREAK key
+- reset_n <= hard_reset_n and not keyb_break;
+-
+- -- Clock enable generation - 32 MHz clock split into 32 cycles
+- -- CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses)
+- -- Video is on all odd cycles (16 MHz)
+- -- 1 MHz cycles are on cycle 31 (1 MHz)
+- vid_clken <= clken_counter(0); -- 1,3,5...
+- mhz4_clken <= clken_counter(0) and clken_counter(1) and clken_counter(2); -- 7/15/23/31
+- mhz2_clken <= mhz4_clken and clken_counter(3); -- 15/31
+- mhz1_clken <= mhz2_clken and clken_counter(4); -- 31
+- cpu_cycle <= not (clken_counter(0) or clken_counter(1) or clken_counter(2) or clken_counter(3)); -- 0/16
+- cpu_clken <= cpu_cycle and not cpu_cycle_mask;
+-
+- clk_gen: process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- clken_counter <= (others => '0');
+- elsif rising_edge(clock) then
+- clken_counter <= clken_counter + 1;
+- end if;
+- end process;
+-
+- cycle_stretch: process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- cpu_cycle_mask <= '0';
+- elsif rising_edge(clock) and mhz2_clken = '1' then
+- if mhz1_enable = '1' and cpu_cycle_mask = '0' then
+- -- Block CPU cycles until 1 MHz cycle has completed
+- cpu_cycle_mask <= '1';
+- end if;
+- if mhz1_clken = '1' then
+- -- CPU can run again
+- -- FIXME: This may not be correct in terms of CPU cycles, but it
+- -- should work
+- cpu_cycle_mask <= '0';
+- end if;
+- end if;
+- end process;
+-
+- ttxt_clk_gen: process(CLOCK_24(0),reset_n)
+- begin
+- if reset_n = '0' then
+- ttxt_clken_counter <= (others => '0');
+- elsif rising_edge(CLOCK_24(0)) then
+- ttxt_clken_counter <= ttxt_clken_counter + 1;
+- end if;
+- end process;
+-
+- -- 6 MHz clock enable for SAA5050
+- ttxt_clken <= '1' when ttxt_clken_counter = 0 else '0';
+-
+- -- CPU configuration and fixed signals
+- cpu_mode <= "00"; -- 6502
+- cpu_ready <= '1';
+- cpu_abort_n <= '1';
+- cpu_nmi_n <= '1';
+- cpu_so_n <= '1';
+-
+- -- Address decoding
+- -- 0x0000 = 32 KB SRAM
+- -- 0x8000 = 16 KB BASIC/Sideways ROMs
+- -- 0xC000 = 16 KB MOS ROM
+- --
+- -- IO regions are mapped into a hole in the MOS. There are three regions:
+- -- 0xFC00 = FRED
+- -- 0xFD00 = JIM
+- -- 0xFE00 = SHEILA
+- ram_enable <= not cpu_a(15);
+- rom_enable <= cpu_a(15) and not cpu_a(14);
+- mos_enable <= cpu_a(15) and cpu_a(14) and not (io_fred or io_jim or io_sheila);
+- io_fred <= '1' when cpu_a(15 downto 8) = "11111100" else '0';
+- io_jim <= '1' when cpu_a(15 downto 8) = "11111101" else '0';
+- io_sheila <= '1' when cpu_a(15 downto 8) = "11111110" else '0';
+- -- The following IO regions are accessed at 1 MHz and hence will stall the
+- -- CPU accordingly
+- mhz1_enable <= io_fred or io_jim or
+- adc_enable or sys_via_enable or user_via_enable or
+- serproc_enable or acia_enable or crtc_enable;
+-
+- -- SHEILA address demux
+- -- All the system peripherals are mapped into this page as follows:
+- -- 0xFE00 - 0xFE07 = MC6845 CRTC
+- -- 0xFE08 - 0xFE0F = MC6850 ACIA (Serial/Tape)
+- -- 0xFE10 - 0xFE1F = Serial ULA
+- -- 0xFE20 - 0xFE2F = Video ULA
+- -- 0xFE30 - 0xFE3F = Paged ROM select latch
+- -- 0xFE40 - 0xFE5F = System VIA (6522)
+- -- 0xFE60 - 0xFE7F = User VIA (6522)
+- -- 0xFE80 - 0xFE9F = 8271 Floppy disc controller
+- -- 0xFEA0 - 0xFEBF = 68B54 ADLC for Econet
+- -- 0xFEC0 - 0xFEDF = uPD7002 ADC
+- -- 0xFEE0 - 0xFEFF = Tube ULA
+- process(cpu_a,io_sheila)
+- begin
+- -- All regions normally de-selected
+- crtc_enable <= '0';
+- acia_enable <= '0';
+- serproc_enable <= '0';
+- vidproc_enable <= '0';
+- romsel_enable <= '0';
+- sys_via_enable <= '0';
+- user_via_enable <= '0';
+- fddc_enable <= '0';
+- adlc_enable <= '0';
+- adc_enable <= '0';
+- tube_enable <= '0';
+-
+- if io_sheila = '1' then
+- case cpu_a(7 downto 5) is
+- when "000" =>
+- -- 0xFE00
+- if cpu_a(4) = '0' then
+- if cpu_a(3) = '0' then
+- -- 0xFE00
+- crtc_enable <= '1';
+- else
+- -- 0xFE08
+- acia_enable <= '1';
+- end if;
+- else
+- -- 0xFE10
+- serproc_enable <= '1';
+- end if;
+- when "001" =>
+- -- 0xFE20
+- if cpu_a(4) = '0' then
+- -- 0xFE20
+- vidproc_enable <= '1';
+- else
+- -- 0xFE30
+- romsel_enable <= '1';
+- end if;
+- when "010" => sys_via_enable <= '1'; -- 0xFE40
+- when "011" => user_via_enable <= '1'; -- 0xFE60
+- when "100" => fddc_enable <= '1'; -- 0xFE80
+- when "101" => adlc_enable <= '1'; -- 0xFEA0
+- when "110" => adc_enable <= '1'; -- 0xFEC0
+- when "111" => tube_enable <= '1'; -- 0xFEE0
+- when others =>
+- null;
+- end case;
+- end if;
+- end process;
+-
+- -- CPU data bus mux and interrupts
+- cpu_di <=
+- SRAM_DQ(7 downto 0) when ram_enable = '1' else
+- FL_DQ when rom_enable = '1' else
+- FL_DQ when mos_enable = '1' else
+- crtc_do when crtc_enable = '1' else
+- "00000010" when acia_enable = '1' else
+- sys_via_do when sys_via_enable = '1' else
+- user_via_do when user_via_enable = '1' else
+- (others => '0'); -- un-decoded locations are pulled down by RP1
+- debug_irq_in_n <= sys_via_irq_n and user_via_irq_n; -- route IRQ through debugger
+- --cpu_irq_n <= sys_via_irq_n and user_via_irq_n;
+-
+- -- ROMs are in external flash and split into 16K slots (since this also suits other
+- -- computers that might be run on the same board).
+- -- The first 8 slots are allocated for use here, and the first 4 are decoded as
+- -- the sideways ROMs. Slot 7 is used for the MOS.
+- FL_RST_N <= reset_n;
+- FL_CE_N <= '0';
+- FL_OE_N <= '0';
+- FL_WE_N <= '1';
+- FL_ADDR(21 downto 17) <= ROM_OFFSET(7 downto 3);
+- FL_ADDR(16 downto 14) <=
+- "111" when mos_enable = '1' else
+- "0" & romsel(1 downto 0);
+- FL_ADDR(13 downto 0) <= cpu_a(13 downto 0);
+-
+- -- SRAM bus
+- SRAM_UB_N <= '1';
+- SRAM_LB_N <= '0';
+- SRAM_CE_N <= '0';
+- SRAM_OE_N <= '0';
+- SRAM_DQ(15 downto 8) <= (others => '0');
+-
+- -- Synchronous outputs to SRAM
+- process(clock,reset_n)
+- variable ram_write : std_logic;
+- begin
+- ram_write := ram_enable and not cpu_r_nw;
+-
+- if reset_n = '0' then
+- SRAM_WE_N <= '1';
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
+- elsif rising_edge(clock) then
+- -- Default to inputs
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
+-
+- -- Register SRAM signals to outputs (clock must be at least 2x CPU clock)
+- if vid_clken = '1' then
+- -- Fetch data from previous CPU cycle
+- SRAM_WE_N <= not ram_write;
+- SRAM_ADDR <= "00" & cpu_a(15 downto 0);
+- if ram_write = '1' then
+- SRAM_DQ(7 downto 0) <= cpu_do;
+- end if;
+- else
+- -- Fetch data from previous display cycle
+- SRAM_WE_N <= '1';
+- SRAM_ADDR <= "000" & display_a;
+- end if;
+- end if;
+- end process;
+-
+- -- Address translation logic for calculation of display address
+- process(crtc_ma,crtc_ra,disp_addr_offs)
+- variable aa : unsigned(3 downto 0);
+- begin
+- if crtc_ma(12) = '0' then
+- -- No adjustment
+- aa := unsigned(crtc_ma(11 downto 8));
+- else
+- -- Address adjusted according to screen mode to compensate for
+- -- wrap at 0x8000.
+- case disp_addr_offs is
+- when "00" =>
+- -- Mode 3 - restart at 0x4000
+- aa := unsigned(crtc_ma(11 downto 8)) + 8;
+- when "01" =>
+- -- Mode 6 - restart at 0x6000
+- aa := unsigned(crtc_ma(11 downto 8)) + 12;
+- when "10" =>
+- -- Mode 0,1,2 - restart at 0x3000
+- aa := unsigned(crtc_ma(11 downto 8)) + 6;
+- when "11" =>
+- -- Mode 4,5 - restart at 0x5800
+- aa := unsigned(crtc_ma(11 downto 8)) + 11;
+- when others =>
+- null;
+- end case;
+- end if;
+-
+- if crtc_ma(13) = '0' then
+- -- HI RES
+- display_a <= std_logic_vector(aa(3 downto 0)) & crtc_ma(7 downto 0) & crtc_ra(2 downto 0);
+- else
+- -- TTX VDU
+- display_a <= std_logic(aa(3)) & "1111" & crtc_ma(9 downto 0);
+- end if;
+- end process;
+-
+- -- VIDPROC
+- vidproc_invert_n <= '1';
+- vidproc_disen <= crtc_de and not crtc_ra(3); -- DISEN is masked off by RA(3) for MODEs 3 and 6
+- r_in <= ttxt_r;
+- g_in <= ttxt_g;
+- b_in <= ttxt_b;
+-
+- -- SAA5050
+- ttxt_glr <= not crtc_hsync;
+- ttxt_dew <= crtc_vsync;
+- ttxt_crs <= not crtc_ra(0);
+- ttxt_lose <= crtc_de;
+-
+- -- CRTC drives video out (CSYNC on HSYNC output, VSYNC high)
+- VGA_HS <= not (crtc_hsync xor crtc_vsync);
+- VGA_VS <= '1';
+- VGA_R <= r_out & r_out & r_out & r_out;
+- VGA_G <= g_out & g_out & g_out & g_out;
+- VGA_B <= b_out & b_out & b_out & b_out;
+-
+- -- Connections to System VIA
+- -- ADC
+- sys_via_cb1_in <= '1'; -- /EOC
+- -- CRTC
+- sys_via_ca1_in <= crtc_vsync;
+- sys_via_cb2_in <= crtc_lpstb;
+- -- Keyboard
+- sys_via_ca2_in <= keyb_int;
+- sys_via_pa_in(7) <= keyb_out;
+- sys_via_pa_in(6 downto 0) <= sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work
+- keyb_column <= sys_via_pa_out(3 downto 0);
+- keyb_row <= sys_via_pa_out(6 downto 4);
+- -- Sound
+- sound_di <= sys_via_pa_out;
+- -- Others (idle until missing bits implemented)
+- sys_via_pb_in(7 downto 4) <= (others => '1');
+-
+- -- Connections to User VIA (user port is output on green LEDs)
+- user_via_ca1_in <= '1'; -- Pulled up
+- --LEDG <= user_via_pb_out;
+-
+- -- MMBEEB
+- user_via_cb1_in <= user_via_pb_out(1);
+- SD_SCLK <= user_via_pb_out(1); -- SCLK
+- SD_MOSI <= user_via_pb_out(0); -- SDO
+- SD_nCS <= '0'; -- CS
+- user_via_cb2_in <= SD_MISO; -- SDI
+- user_via_pb_in <= user_via_pb_out;
+-
+- -- ROM select latch
+- process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- romsel <= (others => '0');
+- elsif rising_edge(clock) then
+- if romsel_enable = '1' and cpu_r_nw = '0' then
+- romsel <= cpu_do(3 downto 0);
+- end if;
+- end if;
+- end process;
+-
+- -- IC32 latch
+- sound_enable_n <= ic32(0);
+- speech_write_n <= ic32(1);
+- speech_read_n <= ic32(2);
+- keyb_enable_n <= ic32(3);
+- disp_addr_offs <= ic32(5 downto 4);
+- caps_lock_led_n <= ic32(6);
+- shift_lock_led_n <= ic32(7);
+-
+- process(clock,reset_n)
+- variable bit_num : integer;
+- begin
+- bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0)));
+-
+- if reset_n = '0' then
+- ic32 <= (others => '0');
+- elsif rising_edge(clock) then
+- ic32(bit_num) <= sys_via_pb_out(3);
+- end if;
+- end process;
+-
+- -- Keyboard LEDs
+- LEDR(0) <= not caps_lock_led_n;
+- LEDR(1) <= not shift_lock_led_n;
+-
+- -----------------
+- -- DEBUG STUFF
+- -----------------
+-
+- GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
+- GPIO_0(1) <= crtc_de;
+-
+-end architecture;
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- BBC B Micro ++-- ++-- Terasic DE1 top-level ++-- ++-- (C) 2011 Mike Stirling ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++-- Generic top-level entity for Altera DE1 board ++entity bbc_micro_de1 is ++generic ( ++ -- ROM offset ++ -- The 4MB Flash is used in 16KB banks as a simple mechanism for ++ -- different machines to address different parts of the ROM, saving ++ -- on re-flashing each time a new machine is run on the board. ++ -- This generic sets the upper 8 address bits. ++ -- Note that the lower bits may be ignored by the implementation, ++ -- e.g. where ROMs are bigger than 16K or where multiple banks ++ -- are required. In this case it is important to ensure that the ++ -- ROM images are aligned correctly (such that these ignored bits are 0). ++ -- ++ -- For the BBC the ROMs start in bank 8 (the first 8 banks are used by ++ -- the Spectrum project). The particular bank is selected by the sideways ++ -- ROM paging register, and bank 7 is used for the MOS. Recommended layout ++ -- is: ++ -- ++ -- 0 Sideways ++ -- 1 Sideways ++ -- 2 Sideways - SuperMMC (DFS) ++ -- 3 Sideways - BASIC ++ -- 4 Not used ++ -- 5 Not used ++ -- 6 Not used ++ -- 7 MOS ++ ROM_OFFSET : std_logic_vector(7 downto 0) := "00001000" ++ ); ++port ( ++ -- Clocks ++ CLOCK_24 : in std_logic_vector(1 downto 0); ++ CLOCK_27 : in std_logic_vector(1 downto 0); ++ CLOCK_50 : in std_logic; ++ EXT_CLOCK : in std_logic; ++ ++ -- Switches ++ SW : in std_logic_vector(9 downto 0); ++ -- Buttons ++ KEY : in std_logic_vector(3 downto 0); ++ ++ -- 7 segment displays ++ HEX0 : out std_logic_vector(6 downto 0); ++ HEX1 : out std_logic_vector(6 downto 0); ++ HEX2 : out std_logic_vector(6 downto 0); ++ HEX3 : out std_logic_vector(6 downto 0); ++ -- Red LEDs ++ LEDR : out std_logic_vector(9 downto 0); ++ -- Green LEDs ++ LEDG : out std_logic_vector(7 downto 0); ++ ++ -- VGA ++ VGA_R : out std_logic_vector(3 downto 0); ++ VGA_G : out std_logic_vector(3 downto 0); ++ VGA_B : out std_logic_vector(3 downto 0); ++ VGA_HS : out std_logic; ++ VGA_VS : out std_logic; ++ ++ -- Serial ++ UART_RXD : in std_logic; ++ UART_TXD : out std_logic; ++ ++ -- PS/2 Keyboard ++ PS2_CLK : inout std_logic; ++ PS2_DAT : inout std_logic; ++ ++ -- I2C ++ I2C_SCLK : inout std_logic; ++ I2C_SDAT : inout std_logic; ++ ++ -- Audio ++ AUD_XCK : out std_logic; ++ AUD_BCLK : out std_logic; ++ AUD_ADCLRCK : out std_logic; ++ AUD_ADCDAT : in std_logic; ++ AUD_DACLRCK : out std_logic; ++ AUD_DACDAT : out std_logic; ++ ++ -- SRAM ++ SRAM_ADDR : out std_logic_vector(17 downto 0); ++ SRAM_DQ : inout std_logic_vector(15 downto 0); ++ SRAM_CE_N : out std_logic; ++ SRAM_OE_N : out std_logic; ++ SRAM_WE_N : out std_logic; ++ SRAM_UB_N : out std_logic; ++ SRAM_LB_N : out std_logic; ++ ++ -- SDRAM ++ DRAM_ADDR : out std_logic_vector(11 downto 0); ++ DRAM_DQ : inout std_logic_vector(15 downto 0); ++ DRAM_BA_0 : in std_logic; ++ DRAM_BA_1 : in std_logic; ++ DRAM_CAS_N : in std_logic; ++ DRAM_CKE : in std_logic; ++ DRAM_CLK : in std_logic; ++ DRAM_CS_N : in std_logic; ++ DRAM_LDQM : in std_logic; ++ DRAM_RAS_N : in std_logic; ++ DRAM_UDQM : in std_logic; ++ DRAM_WE_N : in std_logic; ++ ++ -- Flash ++ FL_ADDR : out std_logic_vector(21 downto 0); ++ FL_DQ : inout std_logic_vector(7 downto 0); ++ FL_RST_N : out std_logic; ++ FL_OE_N : out std_logic; ++ FL_WE_N : out std_logic; ++ FL_CE_N : out std_logic; ++ ++ -- SD card (SPI mode) ++ SD_nCS : out std_logic; ++ SD_MOSI : out std_logic; ++ SD_SCLK : out std_logic; ++ SD_MISO : in std_logic; ++ ++ -- GPIO ++ GPIO_0 : inout std_logic_vector(35 downto 0); ++ GPIO_1 : inout std_logic_vector(35 downto 0) ++ ); ++end entity; ++ ++architecture rtl of bbc_micro_de1 is ++ ++------------------------------ ++-- PLL (32 MHz master clock) ++------------------------------ ++ ++component pll32 IS ++ PORT ++ ( ++ areset : IN STD_LOGIC := '0'; ++ inclk0 : IN STD_LOGIC := '0'; ++ c0 : OUT STD_LOGIC ; ++ locked : OUT STD_LOGIC ++ ); ++end component; ++ ++--------- ++-- CPU ++--------- ++ ++component T65 is ++ port( ++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 ++ Res_n : in std_logic; ++ Enable : in std_logic; ++ Clk : in std_logic; ++ Rdy : in std_logic; ++ Abort_n : in std_logic; ++ IRQ_n : in std_logic; ++ NMI_n : in std_logic; ++ SO_n : in std_logic; ++ R_W_n : out std_logic; ++ Sync : out std_logic; ++ EF : out std_logic; ++ MF : out std_logic; ++ XF : out std_logic; ++ ML_n : out std_logic; ++ VP_n : out std_logic; ++ VDA : out std_logic; ++ VPA : out std_logic; ++ A : out std_logic_vector(23 downto 0); ++ DI : in std_logic_vector(7 downto 0); ++ DO : out std_logic_vector(7 downto 0) ++ ); ++end component; ++ ++----------------- ++-- MC6845 CRTC ++----------------- ++ ++component mc6845 is ++port ( ++ CLOCK : in std_logic; ++ CLKEN : in std_logic; ++ nRESET : in std_logic; ++ ++ -- Bus interface ++ ENABLE : in std_logic; ++ R_nW : in std_logic; ++ RS : in std_logic; ++ DI : in std_logic_vector(7 downto 0); ++ DO : out std_logic_vector(7 downto 0); ++ ++ -- Display interface ++ VSYNC : out std_logic; ++ HSYNC : out std_logic; ++ DE : out std_logic; ++ CURSOR : out std_logic; ++ LPSTB : in std_logic; ++ ++ -- Memory interface ++ MA : out std_logic_vector(13 downto 0); ++ RA : out std_logic_vector(4 downto 0) ++ ); ++end component; ++ ++------------------------- ++-- "VIDPROC" Video ULA ++------------------------- ++ ++component vidproc is ++port ( ++ CLOCK : in std_logic; ++ -- Clock enable qualifies display cycles (interleaved with CPU cycles) ++ CLKEN : in std_logic; ++ nRESET : in std_logic; ++ ++ -- Clock enable output to CRTC ++ CLKEN_CRTC : out std_logic; ++ ++ -- Bus interface ++ ENABLE : in std_logic; ++ A0 : in std_logic; ++ -- CPU data bus (for register writes) ++ DI_CPU : in std_logic_vector(7 downto 0); ++ -- Display RAM data bus (for display data fetch) ++ DI_RAM : in std_logic_vector(7 downto 0); ++ ++ -- Control interface ++ nINVERT : in std_logic; ++ DISEN : in std_logic; ++ CURSOR : in std_logic; ++ ++ -- Video in (teletext mode) ++ R_IN : in std_logic; ++ G_IN : in std_logic; ++ B_IN : in std_logic; ++ ++ -- Video out ++ R : out std_logic; ++ G : out std_logic; ++ B : out std_logic ++ ); ++end component; ++ ++-------------------------------- ++-- SAA5050 Teletext Generator ++-------------------------------- ++ ++component saa5050 is ++port ( ++ CLOCK : in std_logic; ++ -- 6 MHz dot clock enable ++ CLKEN : in std_logic; ++ -- Async reset ++ nRESET : in std_logic; ++ ++ -- Character data input (in the bus clock domain) ++ DI_CLOCK : in std_logic; ++ DI_CLKEN : in std_logic; ++ DI : in std_logic_vector(6 downto 0); ++ ++ -- Timing inputs ++ -- General line reset (not used) ++ GLR : in std_logic; -- /HSYNC ++ -- Data entry window - high during VSYNC. ++ -- Resets ROM row counter and drives 'flash' signal ++ DEW : in std_logic; -- VSYNC ++ -- Character rounding select - high during even field ++ CRS : in std_logic; -- FIELD ++ -- Load output shift register enable - high during active video ++ LOSE : in std_logic; -- DE ++ ++ -- Video out ++ R : out std_logic; ++ G : out std_logic; ++ B : out std_logic; ++ Y : out std_logic ++ ); ++end component; ++ ++-------------- ++-- 6522 VIA ++-------------- ++ ++component M6522 is ++ port ( ++ ++ I_RS : in std_logic_vector(3 downto 0); ++ I_DATA : in std_logic_vector(7 downto 0); ++ O_DATA : out std_logic_vector(7 downto 0); ++ O_DATA_OE_L : out std_logic; ++ ++ I_RW_L : in std_logic; ++ I_CS1 : in std_logic; ++ I_CS2_L : in std_logic; ++ ++ O_IRQ_L : out std_logic; -- note, not open drain ++ -- port a ++ I_CA1 : in std_logic; ++ I_CA2 : in std_logic; ++ O_CA2 : out std_logic; ++ O_CA2_OE_L : out std_logic; ++ ++ I_PA : in std_logic_vector(7 downto 0); ++ O_PA : out std_logic_vector(7 downto 0); ++ O_PA_OE_L : out std_logic_vector(7 downto 0); ++ ++ -- port b ++ I_CB1 : in std_logic; ++ O_CB1 : out std_logic; ++ O_CB1_OE_L : out std_logic; ++ ++ I_CB2 : in std_logic; ++ O_CB2 : out std_logic; ++ O_CB2_OE_L : out std_logic; ++ ++ I_PB : in std_logic_vector(7 downto 0); ++ O_PB : out std_logic_vector(7 downto 0); ++ O_PB_OE_L : out std_logic_vector(7 downto 0); ++ ++ -- FIXME: Revisit timing in this component. Does it really need a 4x clock? ++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__ ++ RESET_L : in std_logic; ++ ENA_4 : in std_logic; -- clk enable (4x system clock rate) ++ CLK : in std_logic ++ ); ++end component; ++ ++----------------------------- ++-- PS/2 Keyboard Emulation ++----------------------------- ++ ++component keyboard is ++port ( ++ CLOCK : in std_logic; ++ nRESET : in std_logic; ++ CLKEN_1MHZ : in std_logic; ++ ++ -- PS/2 interface ++ PS2_CLK : in std_logic; ++ PS2_DATA : in std_logic; ++ ++ -- If 1 then column is incremented automatically at ++ -- 1 MHz rate ++ AUTOSCAN : in std_logic; ++ ++ COLUMN : in std_logic_vector(3 downto 0); ++ ROW : in std_logic_vector(2 downto 0); ++ ++ -- 1 when currently selected key is down (AUTOSCAN disabled) ++ KEYPRESS : out std_logic; ++ -- 1 when any key is down (except row 0) ++ INT : out std_logic; ++ -- BREAK key output - 1 when pressed ++ BREAK_OUT : out std_logic; ++ ++ -- DIP switch inputs ++ DIP_SWITCH : in std_logic_vector(7 downto 0) ++ ); ++end component; ++ ++----------------------------- ++-- SN76489 sound generator ++----------------------------- ++ ++component sn76489_top is ++ ++ generic ( ++ clock_div_16_g : integer := 1 ++ ); ++ port ( ++ clock_i : in std_logic; ++ clock_en_i : in std_logic; ++ res_n_i : in std_logic; ++ ce_n_i : in std_logic; ++ we_n_i : in std_logic; ++ ready_o : out std_logic; ++ d_i : in std_logic_vector(0 to 7); ++ aout_o : out signed(0 to 7) ++ ); ++ ++end component; ++ ++component i2s_intf is ++generic( ++ mclk_rate : positive := 12000000; ++ sample_rate : positive := 8000; ++ preamble : positive := 1; -- I2S ++ word_length : positive := 16 ++ ); ++ ++port ( ++ -- 2x MCLK in (e.g. 24 MHz for WM8731 USB mode) ++ CLK : in std_logic; ++ nRESET : in std_logic; ++ ++ -- Parallel IO ++ PCM_INL : out std_logic_vector(word_length - 1 downto 0); ++ PCM_INR : out std_logic_vector(word_length - 1 downto 0); ++ PCM_OUTL : in std_logic_vector(word_length - 1 downto 0); ++ PCM_OUTR : in std_logic_vector(word_length - 1 downto 0); ++ ++ -- Codec interface (right justified mode) ++ -- MCLK is generated at half of the CLK input ++ I2S_MCLK : out std_logic; ++ -- LRCLK is equal to the sample rate and is synchronous to ++ -- MCLK. It must be related to MCLK by the oversampling ratio ++ -- given in the codec datasheet. ++ I2S_LRCLK : out std_logic; ++ ++ -- Data is shifted out on the falling edge of BCLK, sampled ++ -- on the rising edge. The bit rate is determined such that ++ -- it is fast enough to fit preamble + word_length bits into ++ -- each LRCLK half cycle. The last cycle of each word may be ++ -- stretched to fit to LRCLK. This is OK at least for the ++ -- WM8731 codec. ++ -- The first falling edge of each timeslot is always synchronised ++ -- with the LRCLK edge. ++ I2S_BCLK : out std_logic; ++ -- Output bitstream ++ I2S_DOUT : out std_logic; ++ -- Input bitstream ++ I2S_DIN : in std_logic ++ ); ++end component; ++ ++component i2c_loader is ++generic ( ++ -- Address of slave to be loaded ++ device_address : integer := 16#1a#; ++ -- Number of retries to allow before stopping ++ num_retries : integer := 0; ++ -- Length of clock divider in bits. Resulting bus frequency is ++ -- CLK/2^(log2_divider + 2) ++ log2_divider : integer := 6 ++); ++ ++port ( ++ CLK : in std_logic; ++ nRESET : in std_logic; ++ ++ I2C_SCL : inout std_logic; ++ I2C_SDA : inout std_logic; ++ ++ IS_DONE : out std_logic; ++ IS_ERROR : out std_logic ++ ); ++end component; ++ ++component debugger is ++generic ( ++ -- Set this for a reasonable half flash duration relative to the ++ -- clock frequency ++ flash_divider : natural := 24 ++ ); ++port ( ++ CLOCK : in std_logic; ++ nRESET : in std_logic; ++ -- CPU clock enable in ++ CLKEN_IN : in std_logic; ++ -- Gated clock enable back out to CPU ++ CLKEN_OUT : out std_logic; ++ -- CPU IRQ in ++ nIRQ_IN : in std_logic; ++ -- Gated IRQ back out to CPU (no interrupts when single stepping) ++ nIRQ_OUT : out std_logic; ++ ++ -- CPU ++ A_CPU : in std_logic_vector(15 downto 0); ++ R_nW : in std_logic; ++ SYNC : in std_logic; ++ ++ -- Aux bus input for display in hex ++ AUX_BUS : in std_logic_vector(15 downto 0); ++ ++ -- Controls ++ -- RUN or HALT CPU ++ RUN : in std_logic; ++ -- Push button to single-step in HALT mode ++ nSTEP : in std_logic; ++ -- Push button to cycle display mode ++ nMODE : in std_logic; ++ -- Push button to cycle display digit in edit mode ++ nDIGIT : in std_logic; ++ -- Push button to cycle digit value in edit mode ++ nSET : in std_logic; ++ ++ -- Output to display ++ DIGIT3 : out std_logic_vector(6 downto 0); ++ DIGIT2 : out std_logic_vector(6 downto 0); ++ DIGIT1 : out std_logic_vector(6 downto 0); ++ DIGIT0 : out std_logic_vector(6 downto 0); ++ ++ LED_BREAKPOINT : out std_logic; ++ LED_WATCHPOINT : out std_logic ++ ); ++end component; ++ ++------------- ++-- Signals ++------------- ++ ++-- Master clock - 32 MHz ++signal pll_reset : std_logic; ++signal pll_locked : std_logic; ++signal clock : std_logic; ++signal hard_reset_n : std_logic; ++signal reset_n : std_logic; ++ ++-- Clock enable counter ++-- CPU and video cycles are interleaved. The CPU runs at 2 MHz (every 16th ++-- cycle) and the video subsystem is enabled on every odd cycle. ++signal clken_counter : unsigned(4 downto 0); ++signal cpu_cycle : std_logic; -- Qualifies all 2 MHz cycles ++signal cpu_cycle_mask : std_logic; -- Set to mask CPU cycles until 1 MHz cycle is complete ++signal cpu_clken : std_logic; -- 2 MHz cycles in which the CPU is enabled ++signal cpu_debug_clken : std_logic; -- CPU clken return from hardware debugger ++-- IO cycles are out of phase with the CPU ++signal vid_clken : std_logic; -- 16 MHz video cycles ++signal mhz4_clken : std_logic; -- Used by 6522 ++signal mhz2_clken : std_logic; -- Used for latching CPU address for clock stretch ++signal mhz1_clken : std_logic; -- 1 MHz bus and associated peripherals, 6522 phase 2 ++-- SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock ++signal ttxt_clken_counter : unsigned(1 downto 0); ++signal ttxt_clken : std_logic; ++ ++-- Debugger connections ++signal debug_irq_in_n : std_logic; ++signal debug_aux : std_logic_vector(15 downto 0); ++ ++-- CPU signals ++signal cpu_mode : std_logic_vector(1 downto 0); ++signal cpu_ready : std_logic; ++signal cpu_abort_n : std_logic; ++signal cpu_irq_n : std_logic; ++signal cpu_nmi_n : std_logic; ++signal cpu_so_n : std_logic; ++signal cpu_r_nw : std_logic; ++signal cpu_sync : std_logic; ++signal cpu_ef : std_logic; ++signal cpu_mf : std_logic; ++signal cpu_xf : std_logic; ++signal cpu_ml_n : std_logic; ++signal cpu_vp_n : std_logic; ++signal cpu_vda : std_logic; ++signal cpu_vpa : std_logic; ++signal cpu_a : std_logic_vector(23 downto 0); ++signal cpu_di : std_logic_vector(7 downto 0); ++signal cpu_do : std_logic_vector(7 downto 0); ++ ++-- CRTC signals ++signal crtc_clken : std_logic; ++signal crtc_do : std_logic_vector(7 downto 0); ++signal crtc_vsync : std_logic; ++signal crtc_hsync : std_logic; ++signal crtc_de : std_logic; ++signal crtc_cursor : std_logic; ++signal crtc_lpstb : std_logic := '0'; ++signal crtc_ma : std_logic_vector(13 downto 0); ++signal crtc_ra : std_logic_vector(4 downto 0); ++ ++-- Decoded display address after address translation for hardware ++-- scrolling ++signal display_a : std_logic_vector(14 downto 0); ++ ++-- "VIDPROC" signals ++signal vidproc_invert_n : std_logic; ++signal vidproc_disen : std_logic; ++signal r_in : std_logic; ++signal g_in : std_logic; ++signal b_in : std_logic; ++signal r_out : std_logic; ++signal g_out : std_logic; ++signal b_out : std_logic; ++ ++-- SAA5050 signals ++signal ttxt_glr : std_logic; ++signal ttxt_dew : std_logic; ++signal ttxt_crs : std_logic; ++signal ttxt_lose : std_logic; ++signal ttxt_r : std_logic; ++signal ttxt_g : std_logic; ++signal ttxt_b : std_logic; ++signal ttxt_y : std_logic; ++ ++-- System VIA signals ++signal sys_via_do : std_logic_vector(7 downto 0); ++signal sys_via_do_oe_n : std_logic; ++signal sys_via_irq_n : std_logic; ++signal sys_via_ca1_in : std_logic := '0'; ++signal sys_via_ca2_in : std_logic := '0'; ++signal sys_via_ca2_out : std_logic; ++signal sys_via_ca2_oe_n : std_logic; ++signal sys_via_pa_in : std_logic_vector(7 downto 0); ++signal sys_via_pa_out : std_logic_vector(7 downto 0); ++signal sys_via_pa_oe_n : std_logic_vector(7 downto 0); ++signal sys_via_cb1_in : std_logic := '0'; ++signal sys_via_cb1_out : std_logic; ++signal sys_via_cb1_oe_n : std_logic; ++signal sys_via_cb2_in : std_logic := '0'; ++signal sys_via_cb2_out : std_logic; ++signal sys_via_cb2_oe_n : std_logic; ++signal sys_via_pb_in : std_logic_vector(7 downto 0); ++signal sys_via_pb_out : std_logic_vector(7 downto 0); ++signal sys_via_pb_oe_n : std_logic_vector(7 downto 0); ++ ++-- User VIA signals ++signal user_via_do : std_logic_vector(7 downto 0); ++signal user_via_do_oe_n : std_logic; ++signal user_via_irq_n : std_logic; ++signal user_via_ca1_in : std_logic := '0'; ++signal user_via_ca2_in : std_logic := '0'; ++signal user_via_ca2_out : std_logic; ++signal user_via_ca2_oe_n : std_logic; ++signal user_via_pa_in : std_logic_vector(7 downto 0); ++signal user_via_pa_out : std_logic_vector(7 downto 0); ++signal user_via_pa_oe_n : std_logic_vector(7 downto 0); ++signal user_via_cb1_in : std_logic := '0'; ++signal user_via_cb1_out : std_logic; ++signal user_via_cb1_oe_n : std_logic; ++signal user_via_cb2_in : std_logic := '0'; ++signal user_via_cb2_out : std_logic; ++signal user_via_cb2_oe_n : std_logic; ++signal user_via_pb_in : std_logic_vector(7 downto 0); ++signal user_via_pb_out : std_logic_vector(7 downto 0); ++signal user_via_pb_oe_n : std_logic_vector(7 downto 0); ++ ++-- IC32 latch on System VIA ++signal ic32 : std_logic_vector(7 downto 0); ++signal sound_enable_n : std_logic; ++signal speech_read_n : std_logic; ++signal speech_write_n : std_logic; ++signal keyb_enable_n : std_logic; ++signal disp_addr_offs : std_logic_vector(1 downto 0); ++signal caps_lock_led_n : std_logic; ++signal shift_lock_led_n : std_logic; ++ ++-- Keyboard ++signal keyb_column : std_logic_vector(3 downto 0); ++signal keyb_row : std_logic_vector(2 downto 0); ++signal keyb_out : std_logic; ++signal keyb_int : std_logic; ++signal keyb_break : std_logic; ++ ++-- Sound generator ++signal sound_ready : std_logic; ++signal sound_di : std_logic_vector(7 downto 0); ++signal sound_ao : signed(7 downto 0); ++signal pcm_inl : std_logic_vector(15 downto 0); ++signal pcm_inr : std_logic_vector(15 downto 0); ++ ++-- Memory enables ++signal ram_enable : std_logic; -- 0x0000 ++signal rom_enable : std_logic; -- 0x8000 (BASIC/sideways ROMs) ++signal mos_enable : std_logic; -- 0xC000 ++-- IO region enables ++signal io_fred : std_logic; -- 0xFC00 (1 MHz bus) ++signal io_jim : std_logic; -- 0xFD00 (1 MHz bus) ++signal io_sheila : std_logic; -- 0xFE00 (System peripherals) ++-- SHIELA ++signal crtc_enable : std_logic; -- 0xFE00-FE07 ++signal acia_enable : std_logic; -- 0xFE08-FE0F ++signal serproc_enable : std_logic; -- 0xFE10-FE1F ++signal vidproc_enable : std_logic; -- 0xFE20-FE2F ++signal romsel_enable : std_logic; -- 0xFE30-FE3F ++signal sys_via_enable : std_logic; -- 0xFE40-FE5F ++signal user_via_enable : std_logic; -- 0xFE60-FE7F ++signal fddc_enable : std_logic; -- 0xFE80-FE9F ++signal adlc_enable : std_logic; -- 0xFEA0-FEBF (Econet) ++signal adc_enable : std_logic; -- 0xFEC0-FEDF ++signal tube_enable : std_logic; -- 0xFEE0-FEFF ++ ++-- ROM select latch ++signal romsel : std_logic_vector(3 downto 0); ++ ++signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral ++ ++begin ++ ------------------------- ++ -- COMPONENT INSTANCES ++ ------------------------- ++ ++ -- 32 MHz master clock ++ pll: pll32 port map ( ++ pll_reset, ++ CLOCK_24(0), ++ clock, ++ pll_locked ); ++ ++ -- Hardware debugger block (single-step, breakpoints) ++ debug: debugger port map ( ++ clock, ++ hard_reset_n, ++ cpu_clken, ++ cpu_debug_clken, ++ debug_irq_in_n, ++ cpu_irq_n, ++ cpu_a(15 downto 0), cpu_r_nw, cpu_sync, ++ debug_aux, ++ SW(8), -- RUN ++ KEY(3), -- STEP ++ KEY(2), -- MODE ++ KEY(1), -- DIGIT ++ KEY(0), -- SET ++ HEX3, HEX2, HEX1, HEX0, ++ LEDR(3), -- BREAKPOINT ++ LEDR(2) -- WATCHPOINT ++ ); ++ ++ -- 6502 CPU ++ cpu : T65 port map ( ++ cpu_mode, ++ reset_n, ++ cpu_debug_clken, ++ clock, ++ cpu_ready, ++ cpu_abort_n, ++ cpu_irq_n, ++ cpu_nmi_n, ++ cpu_so_n, ++ cpu_r_nw, ++ cpu_sync, ++ cpu_ef, ++ cpu_mf, ++ cpu_xf, ++ cpu_ml_n, ++ cpu_vp_n, ++ cpu_vda, ++ cpu_vpa, ++ cpu_a, ++ cpu_di, ++ cpu_do ); ++ ++ crtc : mc6845 port map ( ++ clock, ++ crtc_clken, ++ reset_n, ++ crtc_enable, ++ cpu_r_nw, ++ cpu_a(0), ++ cpu_do, ++ crtc_do, ++ crtc_vsync, ++ crtc_hsync, ++ crtc_de, ++ crtc_cursor, ++ crtc_lpstb, ++ crtc_ma, ++ crtc_ra ); ++ ++ video_ula : vidproc port map ( ++ clock, ++ vid_clken, ++ reset_n, ++ crtc_clken, ++ vidproc_enable, ++ cpu_a(0), ++ cpu_do, ++ SRAM_DQ(7 downto 0), ++ vidproc_invert_n, ++ vidproc_disen, ++ crtc_cursor, ++ r_in, g_in, b_in, ++ r_out, g_out, b_out ++ ); ++ ++ teletext : saa5050 port map ( ++ CLOCK_24(0), -- This runs at 6 MHz, which we can't derive from the 32 MHz clock ++ ttxt_clken, ++ reset_n, ++ clock, -- Data input is synchronised from the bus clock domain ++ vid_clken, ++ SRAM_DQ(6 downto 0), ++ ttxt_glr, ++ ttxt_dew, ++ ttxt_crs, ++ ttxt_lose, ++ ttxt_r, ttxt_g, ttxt_b, ttxt_y ++ ); ++ ++ -- System VIA ++ system_via : m6522 port map ( ++ cpu_a(3 downto 0), ++ cpu_do, ++ sys_via_do, ++ sys_via_do_oe_n, ++ cpu_r_nw, ++ sys_via_enable, ++ '0', -- nCS2 ++ sys_via_irq_n, ++ sys_via_ca1_in, ++ sys_via_ca2_in, ++ sys_via_ca2_out, ++ sys_via_ca2_oe_n, ++ sys_via_pa_in, ++ sys_via_pa_out, ++ sys_via_pa_oe_n, ++ sys_via_cb1_in, ++ sys_via_cb1_out, ++ sys_via_cb1_oe_n, ++ sys_via_cb2_in, ++ sys_via_cb2_out, ++ sys_via_cb2_oe_n, ++ sys_via_pb_in, ++ sys_via_pb_out, ++ sys_via_pb_oe_n, ++ mhz1_clken, ++ hard_reset_n, -- System VIA is reset by power on reset only ++ mhz4_clken, ++ clock ++ ); ++ ++ -- User VIA ++ user_via : m6522 port map ( ++ cpu_a(3 downto 0), ++ cpu_do, ++ user_via_do, ++ user_via_do_oe_n, ++ cpu_r_nw, ++ user_via_enable, ++ '0', -- nCS2 ++ user_via_irq_n, ++ user_via_ca1_in, ++ user_via_ca2_in, ++ user_via_ca2_out, ++ user_via_ca2_oe_n, ++ user_via_pa_in, ++ user_via_pa_out, ++ user_via_pa_oe_n, ++ user_via_cb1_in, ++ user_via_cb1_out, ++ user_via_cb1_oe_n, ++ user_via_cb2_in, ++ user_via_cb2_out, ++ user_via_cb2_oe_n, ++ user_via_pb_in, ++ user_via_pb_out, ++ user_via_pb_oe_n, ++ mhz1_clken, ++ reset_n, ++ mhz4_clken, ++ clock ++ ); ++ ++ -- Keyboard ++ keyb : keyboard port map ( ++ clock, hard_reset_n, mhz1_clken, ++ PS2_CLK, PS2_DAT, ++ keyb_enable_n, ++ keyb_column, ++ keyb_row, ++ keyb_out, ++ keyb_int, ++ keyb_break, ++ SW(7 downto 0) ++ ); ++ ++ -- Sound generator (and drive logic for I2S codec) ++ sound : sn76489_top port map ( ++ clock, mhz4_clken, ++ reset_n, '0', sound_enable_n, ++ sound_ready, sound_di, ++ sound_ao ++ ); ++ i2s : i2s_intf port map ( ++ CLOCK_24(0), reset_n, ++ pcm_inl, pcm_inr, ++ std_logic_vector(sound_ao) & "00000000", ++ std_logic_vector(sound_ao) & "00000000", ++ AUD_XCK, AUD_DACLRCK, ++ AUD_BCLK, AUD_DACDAT, AUD_ADCDAT ++ ); ++ i2c : i2c_loader ++ generic map ( ++ log2_divider => 7 ++ ) ++ port map ( ++ clock, reset_n, ++ I2C_SCLK, I2C_SDAT, ++ LEDR(5), -- IS_DONE ++ LEDR(4) -- IS_ERROR ++ ); ++ ++ -- Asynchronous reset ++ -- PLL is reset by external reset switch ++ pll_reset <= not SW(9); ++ -- Keyboard and System VIA are reset by external reset switch or PLL being out of lock ++ hard_reset_n <= not (pll_reset or not pll_locked); ++ -- Rest of system is reset by all of the above plus the keyboard BREAK key ++ reset_n <= hard_reset_n and not keyb_break; ++ ++ -- Clock enable generation - 32 MHz clock split into 32 cycles ++ -- CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses) ++ -- Video is on all odd cycles (16 MHz) ++ -- 1 MHz cycles are on cycle 31 (1 MHz) ++ vid_clken <= clken_counter(0); -- 1,3,5... ++ mhz4_clken <= clken_counter(0) and clken_counter(1) and clken_counter(2); -- 7/15/23/31 ++ mhz2_clken <= mhz4_clken and clken_counter(3); -- 15/31 ++ mhz1_clken <= mhz2_clken and clken_counter(4); -- 31 ++ cpu_cycle <= not (clken_counter(0) or clken_counter(1) or clken_counter(2) or clken_counter(3)); -- 0/16 ++ cpu_clken <= cpu_cycle and not cpu_cycle_mask; ++ ++ clk_gen: process(clock,reset_n) ++ begin ++ if reset_n = '0' then ++ clken_counter <= (others => '0'); ++ elsif rising_edge(clock) then ++ clken_counter <= clken_counter + 1; ++ end if; ++ end process; ++ ++ cycle_stretch: process(clock,reset_n) ++ begin ++ if reset_n = '0' then ++ cpu_cycle_mask <= '0'; ++ elsif rising_edge(clock) and mhz2_clken = '1' then ++ if mhz1_enable = '1' and cpu_cycle_mask = '0' then ++ -- Block CPU cycles until 1 MHz cycle has completed ++ cpu_cycle_mask <= '1'; ++ end if; ++ if mhz1_clken = '1' then ++ -- CPU can run again ++ -- FIXME: This may not be correct in terms of CPU cycles, but it ++ -- should work ++ cpu_cycle_mask <= '0'; ++ end if; ++ end if; ++ end process; ++ ++ ttxt_clk_gen: process(CLOCK_24(0),reset_n) ++ begin ++ if reset_n = '0' then ++ ttxt_clken_counter <= (others => '0'); ++ elsif rising_edge(CLOCK_24(0)) then ++ ttxt_clken_counter <= ttxt_clken_counter + 1; ++ end if; ++ end process; ++ ++ -- 6 MHz clock enable for SAA5050 ++ ttxt_clken <= '1' when ttxt_clken_counter = 0 else '0'; ++ ++ -- CPU configuration and fixed signals ++ cpu_mode <= "00"; -- 6502 ++ cpu_ready <= '1'; ++ cpu_abort_n <= '1'; ++ cpu_nmi_n <= '1'; ++ cpu_so_n <= '1'; ++ ++ -- Address decoding ++ -- 0x0000 = 32 KB SRAM ++ -- 0x8000 = 16 KB BASIC/Sideways ROMs ++ -- 0xC000 = 16 KB MOS ROM ++ -- ++ -- IO regions are mapped into a hole in the MOS. There are three regions: ++ -- 0xFC00 = FRED ++ -- 0xFD00 = JIM ++ -- 0xFE00 = SHEILA ++ ram_enable <= not cpu_a(15); ++ rom_enable <= cpu_a(15) and not cpu_a(14); ++ mos_enable <= cpu_a(15) and cpu_a(14) and not (io_fred or io_jim or io_sheila); ++ io_fred <= '1' when cpu_a(15 downto 8) = "11111100" else '0'; ++ io_jim <= '1' when cpu_a(15 downto 8) = "11111101" else '0'; ++ io_sheila <= '1' when cpu_a(15 downto 8) = "11111110" else '0'; ++ -- The following IO regions are accessed at 1 MHz and hence will stall the ++ -- CPU accordingly ++ mhz1_enable <= io_fred or io_jim or ++ adc_enable or sys_via_enable or user_via_enable or ++ serproc_enable or acia_enable or crtc_enable; ++ ++ -- SHEILA address demux ++ -- All the system peripherals are mapped into this page as follows: ++ -- 0xFE00 - 0xFE07 = MC6845 CRTC ++ -- 0xFE08 - 0xFE0F = MC6850 ACIA (Serial/Tape) ++ -- 0xFE10 - 0xFE1F = Serial ULA ++ -- 0xFE20 - 0xFE2F = Video ULA ++ -- 0xFE30 - 0xFE3F = Paged ROM select latch ++ -- 0xFE40 - 0xFE5F = System VIA (6522) ++ -- 0xFE60 - 0xFE7F = User VIA (6522) ++ -- 0xFE80 - 0xFE9F = 8271 Floppy disc controller ++ -- 0xFEA0 - 0xFEBF = 68B54 ADLC for Econet ++ -- 0xFEC0 - 0xFEDF = uPD7002 ADC ++ -- 0xFEE0 - 0xFEFF = Tube ULA ++ process(cpu_a,io_sheila) ++ begin ++ -- All regions normally de-selected ++ crtc_enable <= '0'; ++ acia_enable <= '0'; ++ serproc_enable <= '0'; ++ vidproc_enable <= '0'; ++ romsel_enable <= '0'; ++ sys_via_enable <= '0'; ++ user_via_enable <= '0'; ++ fddc_enable <= '0'; ++ adlc_enable <= '0'; ++ adc_enable <= '0'; ++ tube_enable <= '0'; ++ ++ if io_sheila = '1' then ++ case cpu_a(7 downto 5) is ++ when "000" => ++ -- 0xFE00 ++ if cpu_a(4) = '0' then ++ if cpu_a(3) = '0' then ++ -- 0xFE00 ++ crtc_enable <= '1'; ++ else ++ -- 0xFE08 ++ acia_enable <= '1'; ++ end if; ++ else ++ -- 0xFE10 ++ serproc_enable <= '1'; ++ end if; ++ when "001" => ++ -- 0xFE20 ++ if cpu_a(4) = '0' then ++ -- 0xFE20 ++ vidproc_enable <= '1'; ++ else ++ -- 0xFE30 ++ romsel_enable <= '1'; ++ end if; ++ when "010" => sys_via_enable <= '1'; -- 0xFE40 ++ when "011" => user_via_enable <= '1'; -- 0xFE60 ++ when "100" => fddc_enable <= '1'; -- 0xFE80 ++ when "101" => adlc_enable <= '1'; -- 0xFEA0 ++ when "110" => adc_enable <= '1'; -- 0xFEC0 ++ when "111" => tube_enable <= '1'; -- 0xFEE0 ++ when others => ++ null; ++ end case; ++ end if; ++ end process; ++ ++ -- CPU data bus mux and interrupts ++ cpu_di <= ++ SRAM_DQ(7 downto 0) when ram_enable = '1' else ++ FL_DQ when rom_enable = '1' else ++ FL_DQ when mos_enable = '1' else ++ crtc_do when crtc_enable = '1' else ++ "00000010" when acia_enable = '1' else ++ sys_via_do when sys_via_enable = '1' else ++ user_via_do when user_via_enable = '1' else ++ (others => '0'); -- un-decoded locations are pulled down by RP1 ++ debug_irq_in_n <= sys_via_irq_n and user_via_irq_n; -- route IRQ through debugger ++ --cpu_irq_n <= sys_via_irq_n and user_via_irq_n; ++ ++ -- ROMs are in external flash and split into 16K slots (since this also suits other ++ -- computers that might be run on the same board). ++ -- The first 8 slots are allocated for use here, and the first 4 are decoded as ++ -- the sideways ROMs. Slot 7 is used for the MOS. ++ FL_RST_N <= reset_n; ++ FL_CE_N <= '0'; ++ FL_OE_N <= '0'; ++ FL_WE_N <= '1'; ++ FL_ADDR(21 downto 17) <= ROM_OFFSET(7 downto 3); ++ FL_ADDR(16 downto 14) <= ++ "111" when mos_enable = '1' else ++ "0" & romsel(1 downto 0); ++ FL_ADDR(13 downto 0) <= cpu_a(13 downto 0); ++ ++ -- SRAM bus ++ SRAM_UB_N <= '1'; ++ SRAM_LB_N <= '0'; ++ SRAM_CE_N <= '0'; ++ SRAM_OE_N <= '0'; ++ SRAM_DQ(15 downto 8) <= (others => '0'); ++ ++ -- Synchronous outputs to SRAM ++ process(clock,reset_n) ++ variable ram_write : std_logic; ++ begin ++ ram_write := ram_enable and not cpu_r_nw; ++ ++ if reset_n = '0' then ++ SRAM_WE_N <= '1'; ++ SRAM_DQ(7 downto 0) <= (others => 'Z'); ++ elsif rising_edge(clock) then ++ -- Default to inputs ++ SRAM_DQ(7 downto 0) <= (others => 'Z'); ++ ++ -- Register SRAM signals to outputs (clock must be at least 2x CPU clock) ++ if vid_clken = '1' then ++ -- Fetch data from previous CPU cycle ++ SRAM_WE_N <= not ram_write; ++ SRAM_ADDR <= "00" & cpu_a(15 downto 0); ++ if ram_write = '1' then ++ SRAM_DQ(7 downto 0) <= cpu_do; ++ end if; ++ else ++ -- Fetch data from previous display cycle ++ SRAM_WE_N <= '1'; ++ SRAM_ADDR <= "000" & display_a; ++ end if; ++ end if; ++ end process; ++ ++ -- Address translation logic for calculation of display address ++ process(crtc_ma,crtc_ra,disp_addr_offs) ++ variable aa : unsigned(3 downto 0); ++ begin ++ if crtc_ma(12) = '0' then ++ -- No adjustment ++ aa := unsigned(crtc_ma(11 downto 8)); ++ else ++ -- Address adjusted according to screen mode to compensate for ++ -- wrap at 0x8000. ++ case disp_addr_offs is ++ when "00" => ++ -- Mode 3 - restart at 0x4000 ++ aa := unsigned(crtc_ma(11 downto 8)) + 8; ++ when "01" => ++ -- Mode 6 - restart at 0x6000 ++ aa := unsigned(crtc_ma(11 downto 8)) + 12; ++ when "10" => ++ -- Mode 0,1,2 - restart at 0x3000 ++ aa := unsigned(crtc_ma(11 downto 8)) + 6; ++ when "11" => ++ -- Mode 4,5 - restart at 0x5800 ++ aa := unsigned(crtc_ma(11 downto 8)) + 11; ++ when others => ++ null; ++ end case; ++ end if; ++ ++ if crtc_ma(13) = '0' then ++ -- HI RES ++ display_a <= std_logic_vector(aa(3 downto 0)) & crtc_ma(7 downto 0) & crtc_ra(2 downto 0); ++ else ++ -- TTX VDU ++ display_a <= std_logic(aa(3)) & "1111" & crtc_ma(9 downto 0); ++ end if; ++ end process; ++ ++ -- VIDPROC ++ vidproc_invert_n <= '1'; ++ vidproc_disen <= crtc_de and not crtc_ra(3); -- DISEN is masked off by RA(3) for MODEs 3 and 6 ++ r_in <= ttxt_r; ++ g_in <= ttxt_g; ++ b_in <= ttxt_b; ++ ++ -- SAA5050 ++ ttxt_glr <= not crtc_hsync; ++ ttxt_dew <= crtc_vsync; ++ ttxt_crs <= not crtc_ra(0); ++ ttxt_lose <= crtc_de; ++ ++ -- CRTC drives video out (CSYNC on HSYNC output, VSYNC high) ++ VGA_HS <= not (crtc_hsync xor crtc_vsync); ++ VGA_VS <= '1'; ++ VGA_R <= r_out & r_out & r_out & r_out; ++ VGA_G <= g_out & g_out & g_out & g_out; ++ VGA_B <= b_out & b_out & b_out & b_out; ++ ++ -- Connections to System VIA ++ -- ADC ++ sys_via_cb1_in <= '1'; -- /EOC ++ -- CRTC ++ sys_via_ca1_in <= crtc_vsync; ++ sys_via_cb2_in <= crtc_lpstb; ++ -- Keyboard ++ sys_via_ca2_in <= keyb_int; ++ sys_via_pa_in(7) <= keyb_out; ++ sys_via_pa_in(6 downto 0) <= sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work ++ keyb_column <= sys_via_pa_out(3 downto 0); ++ keyb_row <= sys_via_pa_out(6 downto 4); ++ -- Sound ++ sound_di <= sys_via_pa_out; ++ -- Others (idle until missing bits implemented) ++ sys_via_pb_in(7 downto 4) <= (others => '1'); ++ ++ -- Connections to User VIA (user port is output on green LEDs) ++ user_via_ca1_in <= '1'; -- Pulled up ++ --LEDG <= user_via_pb_out; ++ ++ -- MMBEEB ++ user_via_cb1_in <= user_via_pb_out(1); ++ SD_SCLK <= user_via_pb_out(1); -- SCLK ++ SD_MOSI <= user_via_pb_out(0); -- SDO ++ SD_nCS <= '0'; -- CS ++ user_via_cb2_in <= SD_MISO; -- SDI ++ user_via_pb_in <= user_via_pb_out; ++ ++ -- ROM select latch ++ process(clock,reset_n) ++ begin ++ if reset_n = '0' then ++ romsel <= (others => '0'); ++ elsif rising_edge(clock) then ++ if romsel_enable = '1' and cpu_r_nw = '0' then ++ romsel <= cpu_do(3 downto 0); ++ end if; ++ end if; ++ end process; ++ ++ -- IC32 latch ++ sound_enable_n <= ic32(0); ++ speech_write_n <= ic32(1); ++ speech_read_n <= ic32(2); ++ keyb_enable_n <= ic32(3); ++ disp_addr_offs <= ic32(5 downto 4); ++ caps_lock_led_n <= ic32(6); ++ shift_lock_led_n <= ic32(7); ++ ++ process(clock,reset_n) ++ variable bit_num : integer; ++ begin ++ bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0))); ++ ++ if reset_n = '0' then ++ ic32 <= (others => '0'); ++ elsif rising_edge(clock) then ++ ic32(bit_num) <= sys_via_pb_out(3); ++ end if; ++ end process; ++ ++ -- Keyboard LEDs ++ LEDR(0) <= not caps_lock_led_n; ++ LEDR(1) <= not shift_lock_led_n; ++ ++ ----------------- ++ -- DEBUG STUFF ++ ----------------- ++ ++ GPIO_0(0) <= not (crtc_hsync xor crtc_vsync); ++ GPIO_0(1) <= crtc_de; ++ ++end architecture; +diff --git a/bbc_micro_de1_tb.vhd b/bbc_micro_de1_tb.vhd +index 82012ec..9197958 100644 +--- a/bbc_micro_de1_tb.vhd ++++ b/bbc_micro_de1_tb.vhd +@@ -1,299 +1,299 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity bbc_micro_tb is
+-end entity;
+-
+-architecture tb of bbc_micro_tb is
+-component bbc_micro_de1 is
+-port (
+- -- Clocks
+- CLOCK_24 : in std_logic_vector(1 downto 0);
+- CLOCK_27 : in std_logic_vector(1 downto 0);
+- CLOCK_50 : in std_logic;
+- EXT_CLOCK : in std_logic;
+-
+- -- Switches
+- SW : in std_logic_vector(9 downto 0);
+- -- Buttons
+- KEY : in std_logic_vector(3 downto 0);
+-
+- -- 7 segment displays
+- HEX0 : out std_logic_vector(6 downto 0);
+- HEX1 : out std_logic_vector(6 downto 0);
+- HEX2 : out std_logic_vector(6 downto 0);
+- HEX3 : out std_logic_vector(6 downto 0);
+- -- Red LEDs
+- LEDR : out std_logic_vector(9 downto 0);
+- -- Green LEDs
+- LEDG : out std_logic_vector(7 downto 0);
+-
+- -- VGA
+- VGA_R : out std_logic_vector(3 downto 0);
+- VGA_G : out std_logic_vector(3 downto 0);
+- VGA_B : out std_logic_vector(3 downto 0);
+- VGA_HS : out std_logic;
+- VGA_VS : out std_logic;
+-
+- -- Serial
+- UART_RXD : in std_logic;
+- UART_TXD : out std_logic;
+-
+- -- PS/2 Keyboard
+- PS2_CLK : inout std_logic;
+- PS2_DAT : inout std_logic;
+-
+- -- I2C
+- I2C_SCLK : inout std_logic;
+- I2C_SDAT : inout std_logic;
+-
+- -- Audio
+- AUD_XCK : out std_logic;
+- AUD_BCLK : out std_logic;
+- AUD_ADCLRCK : out std_logic;
+- AUD_ADCDAT : in std_logic;
+- AUD_DACLRCK : out std_logic;
+- AUD_DACDAT : out std_logic;
+-
+- -- SRAM
+- SRAM_ADDR : out std_logic_vector(17 downto 0);
+- SRAM_DQ : inout std_logic_vector(15 downto 0);
+- SRAM_CE_N : out std_logic;
+- SRAM_OE_N : out std_logic;
+- SRAM_WE_N : out std_logic;
+- SRAM_UB_N : out std_logic;
+- SRAM_LB_N : out std_logic;
+-
+- -- SDRAM
+- DRAM_ADDR : out std_logic_vector(11 downto 0);
+- DRAM_DQ : inout std_logic_vector(15 downto 0);
+- DRAM_BA_0 : in std_logic;
+- DRAM_BA_1 : in std_logic;
+- DRAM_CAS_N : in std_logic;
+- DRAM_CKE : in std_logic;
+- DRAM_CLK : in std_logic;
+- DRAM_CS_N : in std_logic;
+- DRAM_LDQM : in std_logic;
+- DRAM_RAS_N : in std_logic;
+- DRAM_UDQM : in std_logic;
+- DRAM_WE_N : in std_logic;
+-
+- -- Flash
+- FL_ADDR : out std_logic_vector(21 downto 0);
+- FL_DQ : inout std_logic_vector(7 downto 0);
+- FL_RST_N : in std_logic;
+- FL_OE_N : in std_logic;
+- FL_WE_N : in std_logic;
+-
+- -- GPIO
+- GPIO_0 : inout std_logic_vector(35 downto 0);
+- GPIO_1 : inout std_logic_vector(35 downto 0)
+- );
+-end component;
+-
+-
+-signal clock_24 : std_logic_vector(1 downto 0) := "00";
+-signal clock_27 : std_logic_vector(1 downto 0) := "00";
+-signal clock_50 : std_logic := '0';
+-signal ext_clock : std_logic := '0';
+-signal sw : std_logic_vector(9 downto 0);
+-signal key : std_logic_vector(3 downto 0);
+-signal hex0 : std_logic_vector(6 downto 0);
+-signal hex1 : std_logic_vector(6 downto 0);
+-signal hex2 : std_logic_vector(6 downto 0);
+-signal hex3 : std_logic_vector(6 downto 0);
+-signal ledr : std_logic_vector(9 downto 0);
+-signal ledg : std_logic_vector(7 downto 0);
+-signal vga_r : std_logic_vector(3 downto 0);
+-signal vga_g : std_logic_vector(3 downto 0);
+-signal vga_b : std_logic_vector(3 downto 0);
+-signal vga_hs : std_logic;
+-signal vga_vs : std_logic;
+-signal uart_rxd : std_logic;
+-signal uart_txd : std_logic;
+-signal ps2_clk : std_logic;
+-signal ps2_dat : std_logic;
+-signal i2c_sclk : std_logic;
+-signal i2c_sdat : std_logic;
+-signal aud_xck : std_logic;
+-signal aud_bclk : std_logic;
+-signal aud_adclrck : std_logic;
+-signal aud_adcdat : std_logic;
+-signal aud_daclrck : std_logic;
+-signal aud_dacdat : std_logic;
+-signal sram_addr : std_logic_vector(17 downto 0);
+-signal sram_dq : std_logic_vector(15 downto 0);
+-signal sram_ce_n : std_logic;
+-signal sram_oe_n : std_logic;
+-signal sram_we_n : std_logic;
+-signal sram_ub_n : std_logic;
+-signal sram_lb_n : std_logic;
+-signal dram_addr : std_logic_vector(11 downto 0);
+-signal dram_dq : std_logic_vector(15 downto 0);
+-signal dram_ba_0 : std_logic;
+-signal dram_ba_1 : std_logic;
+-signal dram_cas_n : std_logic;
+-signal dram_cke : std_logic;
+-signal dram_clk : std_logic;
+-signal dram_cs_n : std_logic;
+-signal dram_ldqm : std_logic;
+-signal dram_ras_n : std_logic;
+-signal dram_udqm : std_logic;
+-signal dram_we_n : std_logic;
+-signal fl_addr : std_logic_vector(21 downto 0);
+-signal fl_dq : std_logic_vector(7 downto 0);
+-signal fl_rst_n : std_logic;
+-signal fl_oe_n : std_logic;
+-signal fl_we_n : std_logic;
+-signal gpio_0 : std_logic_vector(35 downto 0);
+-signal gpio_1 : std_logic_vector(35 downto 0);
+-
+-signal n_reset : std_logic := '0';
+-signal n_slow : std_logic := '1';
+-
+-type ram_t is array(0 to 65535) of std_logic_vector(15 downto 0);
+-signal ram : ram_t;
+-signal ram_a : std_logic_vector(15 downto 0);
+-begin
+-
+- uut: bbc_micro_de1 port map (
+- clock_24,
+- clock_27,
+- clock_50,
+- ext_clock,
+- sw,
+- key,
+- hex0,
+- hex1,
+- hex2,
+- hex3,
+- ledr,
+- ledg,
+- vga_r,
+- vga_g,
+- vga_b,
+- vga_hs,
+- vga_vs,
+- uart_rxd,
+- uart_txd,
+- ps2_clk,
+- ps2_dat,
+- i2c_sclk,
+- i2c_sdat,
+- aud_xck,
+- aud_bclk,
+- aud_adclrck,
+- aud_adcdat,
+- aud_daclrck,
+- aud_dacdat,
+- sram_addr,
+- sram_dq,
+- sram_ce_n,
+- sram_oe_n,
+- sram_we_n,
+- sram_ub_n,
+- sram_lb_n,
+- dram_addr,
+- dram_dq,
+- dram_ba_0,
+- dram_ba_1,
+- dram_cas_n,
+- dram_cke,
+- dram_clk,
+- dram_cs_n,
+- dram_ldqm,
+- dram_ras_n,
+- dram_udqm,
+- dram_we_n,
+- fl_addr,
+- fl_dq,
+- fl_rst_n,
+- fl_oe_n,
+- fl_we_n,
+- gpio_0,
+- gpio_1
+- );
+-
+- sw <= n_reset & n_slow & "00000101";
+- clock_50 <= not clock_50 after 10 ns;
+- clock_27(0) <= not clock_27(0) after 18.5 ns;
+- clock_27(1) <= not clock_27(1) after 18.5 ns;
+- clock_24(0) <= not clock_24(0) after 20.8 ns;
+- clock_24(1) <= not clock_24(1) after 20.8 ns;
+-
+- reset: process
+- begin
+- wait for 100 ns;
+- n_reset <= '1';
+- end process;
+-
+- sram: process(sram_addr,sram_dq,sram_ce_n,sram_oe_n,sram_we_n,sram_ub_n,sram_lb_n)
+- begin
+- if sram_ce_n = '0' then
+- if sram_oe_n = '0' and sram_we_n = '1' then
+- if sram_ub_n = '0' then
+- sram_dq(15 downto 8) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8);
+- else
+- sram_dq(15 downto 8) <= (others => 'Z');
+- end if;
+- if sram_lb_n = '0' then
+- sram_dq(7 downto 0) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0);
+- else
+- sram_dq(7 downto 0) <= (others => 'Z');
+- end if;
+- else
+- sram_dq(15 downto 0) <= (others => 'Z');
+- if sram_we_n = '0' then
+- if sram_ub_n = '0' then
+- ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8) <= sram_dq(15 downto 8);
+- end if;
+- if sram_lb_n = '0' then
+- ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0) <= sram_dq(7 downto 0);
+- end if;
+- end if;
+- end if;
+- else
+- sram_dq <= (others => 'Z');
+- end if;
+- end process;
+-
+-
+-end architecture;
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity bbc_micro_tb is ++end entity; ++ ++architecture tb of bbc_micro_tb is ++component bbc_micro_de1 is ++port ( ++ -- Clocks ++ CLOCK_24 : in std_logic_vector(1 downto 0); ++ CLOCK_27 : in std_logic_vector(1 downto 0); ++ CLOCK_50 : in std_logic; ++ EXT_CLOCK : in std_logic; ++ ++ -- Switches ++ SW : in std_logic_vector(9 downto 0); ++ -- Buttons ++ KEY : in std_logic_vector(3 downto 0); ++ ++ -- 7 segment displays ++ HEX0 : out std_logic_vector(6 downto 0); ++ HEX1 : out std_logic_vector(6 downto 0); ++ HEX2 : out std_logic_vector(6 downto 0); ++ HEX3 : out std_logic_vector(6 downto 0); ++ -- Red LEDs ++ LEDR : out std_logic_vector(9 downto 0); ++ -- Green LEDs ++ LEDG : out std_logic_vector(7 downto 0); ++ ++ -- VGA ++ VGA_R : out std_logic_vector(3 downto 0); ++ VGA_G : out std_logic_vector(3 downto 0); ++ VGA_B : out std_logic_vector(3 downto 0); ++ VGA_HS : out std_logic; ++ VGA_VS : out std_logic; ++ ++ -- Serial ++ UART_RXD : in std_logic; ++ UART_TXD : out std_logic; ++ ++ -- PS/2 Keyboard ++ PS2_CLK : inout std_logic; ++ PS2_DAT : inout std_logic; ++ ++ -- I2C ++ I2C_SCLK : inout std_logic; ++ I2C_SDAT : inout std_logic; ++ ++ -- Audio ++ AUD_XCK : out std_logic; ++ AUD_BCLK : out std_logic; ++ AUD_ADCLRCK : out std_logic; ++ AUD_ADCDAT : in std_logic; ++ AUD_DACLRCK : out std_logic; ++ AUD_DACDAT : out std_logic; ++ ++ -- SRAM ++ SRAM_ADDR : out std_logic_vector(17 downto 0); ++ SRAM_DQ : inout std_logic_vector(15 downto 0); ++ SRAM_CE_N : out std_logic; ++ SRAM_OE_N : out std_logic; ++ SRAM_WE_N : out std_logic; ++ SRAM_UB_N : out std_logic; ++ SRAM_LB_N : out std_logic; ++ ++ -- SDRAM ++ DRAM_ADDR : out std_logic_vector(11 downto 0); ++ DRAM_DQ : inout std_logic_vector(15 downto 0); ++ DRAM_BA_0 : in std_logic; ++ DRAM_BA_1 : in std_logic; ++ DRAM_CAS_N : in std_logic; ++ DRAM_CKE : in std_logic; ++ DRAM_CLK : in std_logic; ++ DRAM_CS_N : in std_logic; ++ DRAM_LDQM : in std_logic; ++ DRAM_RAS_N : in std_logic; ++ DRAM_UDQM : in std_logic; ++ DRAM_WE_N : in std_logic; ++ ++ -- Flash ++ FL_ADDR : out std_logic_vector(21 downto 0); ++ FL_DQ : inout std_logic_vector(7 downto 0); ++ FL_RST_N : in std_logic; ++ FL_OE_N : in std_logic; ++ FL_WE_N : in std_logic; ++ ++ -- GPIO ++ GPIO_0 : inout std_logic_vector(35 downto 0); ++ GPIO_1 : inout std_logic_vector(35 downto 0) ++ ); ++end component; ++ ++ ++signal clock_24 : std_logic_vector(1 downto 0) := "00"; ++signal clock_27 : std_logic_vector(1 downto 0) := "00"; ++signal clock_50 : std_logic := '0'; ++signal ext_clock : std_logic := '0'; ++signal sw : std_logic_vector(9 downto 0); ++signal key : std_logic_vector(3 downto 0); ++signal hex0 : std_logic_vector(6 downto 0); ++signal hex1 : std_logic_vector(6 downto 0); ++signal hex2 : std_logic_vector(6 downto 0); ++signal hex3 : std_logic_vector(6 downto 0); ++signal ledr : std_logic_vector(9 downto 0); ++signal ledg : std_logic_vector(7 downto 0); ++signal vga_r : std_logic_vector(3 downto 0); ++signal vga_g : std_logic_vector(3 downto 0); ++signal vga_b : std_logic_vector(3 downto 0); ++signal vga_hs : std_logic; ++signal vga_vs : std_logic; ++signal uart_rxd : std_logic; ++signal uart_txd : std_logic; ++signal ps2_clk : std_logic; ++signal ps2_dat : std_logic; ++signal i2c_sclk : std_logic; ++signal i2c_sdat : std_logic; ++signal aud_xck : std_logic; ++signal aud_bclk : std_logic; ++signal aud_adclrck : std_logic; ++signal aud_adcdat : std_logic; ++signal aud_daclrck : std_logic; ++signal aud_dacdat : std_logic; ++signal sram_addr : std_logic_vector(17 downto 0); ++signal sram_dq : std_logic_vector(15 downto 0); ++signal sram_ce_n : std_logic; ++signal sram_oe_n : std_logic; ++signal sram_we_n : std_logic; ++signal sram_ub_n : std_logic; ++signal sram_lb_n : std_logic; ++signal dram_addr : std_logic_vector(11 downto 0); ++signal dram_dq : std_logic_vector(15 downto 0); ++signal dram_ba_0 : std_logic; ++signal dram_ba_1 : std_logic; ++signal dram_cas_n : std_logic; ++signal dram_cke : std_logic; ++signal dram_clk : std_logic; ++signal dram_cs_n : std_logic; ++signal dram_ldqm : std_logic; ++signal dram_ras_n : std_logic; ++signal dram_udqm : std_logic; ++signal dram_we_n : std_logic; ++signal fl_addr : std_logic_vector(21 downto 0); ++signal fl_dq : std_logic_vector(7 downto 0); ++signal fl_rst_n : std_logic; ++signal fl_oe_n : std_logic; ++signal fl_we_n : std_logic; ++signal gpio_0 : std_logic_vector(35 downto 0); ++signal gpio_1 : std_logic_vector(35 downto 0); ++ ++signal n_reset : std_logic := '0'; ++signal n_slow : std_logic := '1'; ++ ++type ram_t is array(0 to 65535) of std_logic_vector(15 downto 0); ++signal ram : ram_t; ++signal ram_a : std_logic_vector(15 downto 0); ++begin ++ ++ uut: bbc_micro_de1 port map ( ++ clock_24, ++ clock_27, ++ clock_50, ++ ext_clock, ++ sw, ++ key, ++ hex0, ++ hex1, ++ hex2, ++ hex3, ++ ledr, ++ ledg, ++ vga_r, ++ vga_g, ++ vga_b, ++ vga_hs, ++ vga_vs, ++ uart_rxd, ++ uart_txd, ++ ps2_clk, ++ ps2_dat, ++ i2c_sclk, ++ i2c_sdat, ++ aud_xck, ++ aud_bclk, ++ aud_adclrck, ++ aud_adcdat, ++ aud_daclrck, ++ aud_dacdat, ++ sram_addr, ++ sram_dq, ++ sram_ce_n, ++ sram_oe_n, ++ sram_we_n, ++ sram_ub_n, ++ sram_lb_n, ++ dram_addr, ++ dram_dq, ++ dram_ba_0, ++ dram_ba_1, ++ dram_cas_n, ++ dram_cke, ++ dram_clk, ++ dram_cs_n, ++ dram_ldqm, ++ dram_ras_n, ++ dram_udqm, ++ dram_we_n, ++ fl_addr, ++ fl_dq, ++ fl_rst_n, ++ fl_oe_n, ++ fl_we_n, ++ gpio_0, ++ gpio_1 ++ ); ++ ++ sw <= n_reset & n_slow & "00000101"; ++ clock_50 <= not clock_50 after 10 ns; ++ clock_27(0) <= not clock_27(0) after 18.5 ns; ++ clock_27(1) <= not clock_27(1) after 18.5 ns; ++ clock_24(0) <= not clock_24(0) after 20.8 ns; ++ clock_24(1) <= not clock_24(1) after 20.8 ns; ++ ++ reset: process ++ begin ++ wait for 100 ns; ++ n_reset <= '1'; ++ end process; ++ ++ sram: process(sram_addr,sram_dq,sram_ce_n,sram_oe_n,sram_we_n,sram_ub_n,sram_lb_n) ++ begin ++ if sram_ce_n = '0' then ++ if sram_oe_n = '0' and sram_we_n = '1' then ++ if sram_ub_n = '0' then ++ sram_dq(15 downto 8) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8); ++ else ++ sram_dq(15 downto 8) <= (others => 'Z'); ++ end if; ++ if sram_lb_n = '0' then ++ sram_dq(7 downto 0) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0); ++ else ++ sram_dq(7 downto 0) <= (others => 'Z'); ++ end if; ++ else ++ sram_dq(15 downto 0) <= (others => 'Z'); ++ if sram_we_n = '0' then ++ if sram_ub_n = '0' then ++ ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8) <= sram_dq(15 downto 8); ++ end if; ++ if sram_lb_n = '0' then ++ ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0) <= sram_dq(7 downto 0); ++ end if; ++ end if; ++ end if; ++ else ++ sram_dq <= (others => 'Z'); ++ end if; ++ end process; ++ ++ ++end architecture; +diff --git a/debugger.vhd b/debugger.vhd +index 1d78bd5..a7a9d7d 100644 +--- a/debugger.vhd ++++ b/debugger.vhd +@@ -1,300 +1,300 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+---
+--- General purpose hardware debugger
+---
+--- (C) 2011 Mike Stirling
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity debugger is
+-generic (
+- -- Set this for a reasonable half flash duration relative to the
+- -- clock frequency
+- flash_divider : natural := 24
+- );
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- -- CPU clock enable in
+- CLKEN_IN : in std_logic;
+- -- Gated clock enable back out to CPU
+- CLKEN_OUT : out std_logic;
+- -- CPU IRQ in
+- nIRQ_IN : in std_logic;
+- -- Gated IRQ back out to CPU (no interrupts when single stepping)
+- nIRQ_OUT : out std_logic;
+-
+- -- CPU
+- A_CPU : in std_logic_vector(15 downto 0);
+- R_nW : in std_logic;
+- SYNC : in std_logic;
+-
+- -- Aux bus input for display in hex
+- AUX_BUS : in std_logic_vector(15 downto 0);
+-
+- -- Controls
+- -- RUN or HALT CPU
+- RUN : in std_logic;
+- -- Push button to single-step in HALT mode
+- nSTEP : in std_logic;
+- -- Push button to cycle display mode
+- nMODE : in std_logic;
+- -- Push button to cycle display digit in edit mode
+- nDIGIT : in std_logic;
+- -- Push button to cycle digit value in edit mode
+- nSET : in std_logic;
+-
+- -- Output to display
+- DIGIT3 : out std_logic_vector(6 downto 0);
+- DIGIT2 : out std_logic_vector(6 downto 0);
+- DIGIT1 : out std_logic_vector(6 downto 0);
+- DIGIT0 : out std_logic_vector(6 downto 0);
+-
+- LED_BREAKPOINT : out std_logic;
+- LED_WATCHPOINT : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of debugger is
+-
+-component seg7 is
+-port (
+- D : in std_logic_vector(3 downto 0);
+- Q : out std_logic_vector(6 downto 0)
+-);
+-end component;
+-
+--- Current display mode
+-type mode_t is (modeAddress,modeBreak,modeWatch,modeAux);
+-signal mode : mode_t;
+--- Current edit digit
+-signal digit : unsigned(1 downto 0);
+--- For flashing selected digit
+-signal counter : unsigned(flash_divider-1 downto 0);
+-signal flash : std_logic;
+--- Selected breakpoint address (stop on instruction fetch)
+-signal breakpoint : std_logic_vector(15 downto 0);
+--- Selected watchpoint address (stop on write)
+-signal watchpoint : std_logic_vector(15 downto 0);
+--- Address of last instruction fetch
+-signal instr_addr : std_logic_vector(15 downto 0);
+--- Break flags
+-signal halt : std_logic;
+--- Set when a request to resume has been received but before
+--- the CPU has run
+-signal resuming : std_logic;
+-
+--- Display interface
+-signal a_display : std_logic_vector(15 downto 0);
+-signal d3_display : std_logic_vector(6 downto 0);
+-signal d2_display : std_logic_vector(6 downto 0);
+-signal d1_display : std_logic_vector(6 downto 0);
+-signal d0_display : std_logic_vector(6 downto 0);
+-
+--- Registered button inputs
+-signal r_step_n : std_logic;
+-signal r_mode_n : std_logic;
+-signal r_digit_n : std_logic;
+-signal r_set_n : std_logic;
+-
+-begin
+- -- Mask CPU clock enable
+- CLKEN_OUT <= CLKEN_IN and not halt;
+- -- Mask interrupt
+- nIRQ_OUT <= nIRQ_IN or not RUN;
+-
+- -- Route selected address to display
+- a_display <= instr_addr when mode = modeAddress else
+- breakpoint when mode = modeBreak else
+- watchpoint when mode = modeWatch else
+- AUX_BUS when mode = modeAux else
+- (others => '0');
+-
+- -- Generate display digits from binary
+- d3 : seg7 port map (a_display(15 downto 12),d3_display);
+- d2 : seg7 port map (a_display(11 downto 8),d2_display);
+- d1 : seg7 port map (a_display(7 downto 4),d1_display);
+- d0 : seg7 port map (a_display(3 downto 0),d0_display);
+-
+- -- Flash selected digit in edit modes
+- DIGIT3 <= d3_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "11") else "1111111";
+- DIGIT2 <= d2_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "10") else "1111111";
+- DIGIT1 <= d1_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "01") else "1111111";
+- DIGIT0 <= d0_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "00") else "1111111";
+-
+- -- Show mode on LEDs
+- LED_BREAKPOINT <= '1' when mode = modeBreak or mode = modeAux else '0';
+- LED_WATCHPOINT <= '1' when mode = modeWatch or mode = modeAux else '0';
+-
+- -- Flash counter
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- counter <= (others => '0');
+- flash <= '0';
+- elsif rising_edge(CLOCK) then
+- counter <= counter + 1;
+- if counter = 0 then
+- flash <= not flash;
+- end if;
+- end if;
+- end process;
+-
+- -- Register buttons, select input mode and digit
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r_mode_n <= '1';
+- r_digit_n <= '1';
+- r_set_n <= '1';
+- mode <= modeAddress;
+- digit <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Register buttons
+- r_mode_n <= nMODE;
+- r_digit_n <= nDIGIT;
+- r_set_n <= nSET;
+-
+- if r_mode_n = '1' and nMODE = '0' then
+- -- Increment mode
+- if mode = modeAddress then
+- mode <= modeBreak;
+- elsif mode = modeBreak then
+- mode <= modeWatch;
+- elsif mode = modeWatch then
+- mode <= modeAux;
+- else
+- mode <= modeAddress;
+- end if;
+- end if;
+- if r_digit_n = '1' and nDIGIT = '0' then
+- -- Increment digit
+- digit <= digit + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Set watchpoint address
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- watchpoint <= (others => '1');
+- elsif rising_edge(CLOCK) and mode = modeWatch then
+- if r_set_n = '1' and nSET = '0' then
+- -- Increment selected digit on each button press
+- case digit is
+- when "00" => watchpoint(3 downto 0) <= std_logic_vector(unsigned(watchpoint(3 downto 0)) + 1);
+- when "01" => watchpoint(7 downto 4) <= std_logic_vector(unsigned(watchpoint(7 downto 4)) + 1);
+- when "10" => watchpoint(11 downto 8) <= std_logic_vector(unsigned(watchpoint(11 downto 8)) + 1);
+- when "11" => watchpoint(15 downto 12) <= std_logic_vector(unsigned(watchpoint(15 downto 12)) + 1);
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- -- Set breakpoint address
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- breakpoint <= (others => '1');
+- elsif rising_edge(CLOCK) and mode = modeBreak then
+- if r_set_n = '1' and nSET = '0' then
+- -- Increment selected digit on each button press
+- case digit is
+- when "00" => breakpoint(3 downto 0) <= std_logic_vector(unsigned(breakpoint(3 downto 0)) + 1);
+- when "01" => breakpoint(7 downto 4) <= std_logic_vector(unsigned(breakpoint(7 downto 4)) + 1);
+- when "10" => breakpoint(11 downto 8) <= std_logic_vector(unsigned(breakpoint(11 downto 8)) + 1);
+- when "11" => breakpoint(15 downto 12) <= std_logic_vector(unsigned(breakpoint(15 downto 12)) + 1);
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- -- CPU control logic
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r_step_n <= '1';
+- halt <= '0';
+- resuming <= '0';
+- instr_addr <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Register single-step button
+- r_step_n <= nSTEP;
+-
+- -- Once the CPU has run we can trigger a new halt
+- if CLKEN_IN = '1' then
+- resuming <= '0';
+- end if;
+-
+- if SYNC = '1' then
+- -- Latch address of instruction fetch
+- instr_addr <= A_CPU;
+- end if;
+-
+- -- Check for halt conditions if we are not resuming from a previous halt
+- if resuming = '0' then
+- if RUN = '0' and SYNC = '1' then
+- -- If not in RUN mode then halt on any instruction fetch
+- -- (single-step)
+- halt <= '1';
+- end if;
+- if A_CPU = breakpoint and SYNC = '1' then
+- -- Halt CPU when instruction fetched from breakpoint address
+- halt <= '1';
+- end if;
+- if A_CPU = watchpoint and SYNC = '0' and R_nW = '0' then
+- -- Halt CPU when data write to watchpoint address
+- halt <= '1';
+- end if;
+- end if;
+-
+- -- Resume or single step when user presses "STEP" button
+- if r_step_n = '1' and nSTEP = '0' then
+- resuming <= '1';
+- halt <= '0';
+- end if;
+- end if;
+- end process;
+-end architecture;
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- ++-- General purpose hardware debugger ++-- ++-- (C) 2011 Mike Stirling ++-- ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity debugger is ++generic ( ++ -- Set this for a reasonable half flash duration relative to the ++ -- clock frequency ++ flash_divider : natural := 24 ++ ); ++port ( ++ CLOCK : in std_logic; ++ nRESET : in std_logic; ++ -- CPU clock enable in ++ CLKEN_IN : in std_logic; ++ -- Gated clock enable back out to CPU ++ CLKEN_OUT : out std_logic; ++ -- CPU IRQ in ++ nIRQ_IN : in std_logic; ++ -- Gated IRQ back out to CPU (no interrupts when single stepping) ++ nIRQ_OUT : out std_logic; ++ ++ -- CPU ++ A_CPU : in std_logic_vector(15 downto 0); ++ R_nW : in std_logic; ++ SYNC : in std_logic; ++ ++ -- Aux bus input for display in hex ++ AUX_BUS : in std_logic_vector(15 downto 0); ++ ++ -- Controls ++ -- RUN or HALT CPU ++ RUN : in std_logic; ++ -- Push button to single-step in HALT mode ++ nSTEP : in std_logic; ++ -- Push button to cycle display mode ++ nMODE : in std_logic; ++ -- Push button to cycle display digit in edit mode ++ nDIGIT : in std_logic; ++ -- Push button to cycle digit value in edit mode ++ nSET : in std_logic; ++ ++ -- Output to display ++ DIGIT3 : out std_logic_vector(6 downto 0); ++ DIGIT2 : out std_logic_vector(6 downto 0); ++ DIGIT1 : out std_logic_vector(6 downto 0); ++ DIGIT0 : out std_logic_vector(6 downto 0); ++ ++ LED_BREAKPOINT : out std_logic; ++ LED_WATCHPOINT : out std_logic ++ ); ++end entity; ++ ++architecture rtl of debugger is ++ ++component seg7 is ++port ( ++ D : in std_logic_vector(3 downto 0); ++ Q : out std_logic_vector(6 downto 0) ++); ++end component; ++ ++-- Current display mode ++type mode_t is (modeAddress,modeBreak,modeWatch,modeAux); ++signal mode : mode_t; ++-- Current edit digit ++signal digit : unsigned(1 downto 0); ++-- For flashing selected digit ++signal counter : unsigned(flash_divider-1 downto 0); ++signal flash : std_logic; ++-- Selected breakpoint address (stop on instruction fetch) ++signal breakpoint : std_logic_vector(15 downto 0); ++-- Selected watchpoint address (stop on write) ++signal watchpoint : std_logic_vector(15 downto 0); ++-- Address of last instruction fetch ++signal instr_addr : std_logic_vector(15 downto 0); ++-- Break flags ++signal halt : std_logic; ++-- Set when a request to resume has been received but before ++-- the CPU has run ++signal resuming : std_logic; ++ ++-- Display interface ++signal a_display : std_logic_vector(15 downto 0); ++signal d3_display : std_logic_vector(6 downto 0); ++signal d2_display : std_logic_vector(6 downto 0); ++signal d1_display : std_logic_vector(6 downto 0); ++signal d0_display : std_logic_vector(6 downto 0); ++ ++-- Registered button inputs ++signal r_step_n : std_logic; ++signal r_mode_n : std_logic; ++signal r_digit_n : std_logic; ++signal r_set_n : std_logic; ++ ++begin ++ -- Mask CPU clock enable ++ CLKEN_OUT <= CLKEN_IN and not halt; ++ -- Mask interrupt ++ nIRQ_OUT <= nIRQ_IN or not RUN; ++ ++ -- Route selected address to display ++ a_display <= instr_addr when mode = modeAddress else ++ breakpoint when mode = modeBreak else ++ watchpoint when mode = modeWatch else ++ AUX_BUS when mode = modeAux else ++ (others => '0'); ++ ++ -- Generate display digits from binary ++ d3 : seg7 port map (a_display(15 downto 12),d3_display); ++ d2 : seg7 port map (a_display(11 downto 8),d2_display); ++ d1 : seg7 port map (a_display(7 downto 4),d1_display); ++ d0 : seg7 port map (a_display(3 downto 0),d0_display); ++ ++ -- Flash selected digit in edit modes ++ DIGIT3 <= d3_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "11") else "1111111"; ++ DIGIT2 <= d2_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "10") else "1111111"; ++ DIGIT1 <= d1_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "01") else "1111111"; ++ DIGIT0 <= d0_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "00") else "1111111"; ++ ++ -- Show mode on LEDs ++ LED_BREAKPOINT <= '1' when mode = modeBreak or mode = modeAux else '0'; ++ LED_WATCHPOINT <= '1' when mode = modeWatch or mode = modeAux else '0'; ++ ++ -- Flash counter ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ counter <= (others => '0'); ++ flash <= '0'; ++ elsif rising_edge(CLOCK) then ++ counter <= counter + 1; ++ if counter = 0 then ++ flash <= not flash; ++ end if; ++ end if; ++ end process; ++ ++ -- Register buttons, select input mode and digit ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ r_mode_n <= '1'; ++ r_digit_n <= '1'; ++ r_set_n <= '1'; ++ mode <= modeAddress; ++ digit <= (others => '0'); ++ elsif rising_edge(CLOCK) then ++ -- Register buttons ++ r_mode_n <= nMODE; ++ r_digit_n <= nDIGIT; ++ r_set_n <= nSET; ++ ++ if r_mode_n = '1' and nMODE = '0' then ++ -- Increment mode ++ if mode = modeAddress then ++ mode <= modeBreak; ++ elsif mode = modeBreak then ++ mode <= modeWatch; ++ elsif mode = modeWatch then ++ mode <= modeAux; ++ else ++ mode <= modeAddress; ++ end if; ++ end if; ++ if r_digit_n = '1' and nDIGIT = '0' then ++ -- Increment digit ++ digit <= digit + 1; ++ end if; ++ end if; ++ end process; ++ ++ -- Set watchpoint address ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ watchpoint <= (others => '1'); ++ elsif rising_edge(CLOCK) and mode = modeWatch then ++ if r_set_n = '1' and nSET = '0' then ++ -- Increment selected digit on each button press ++ case digit is ++ when "00" => watchpoint(3 downto 0) <= std_logic_vector(unsigned(watchpoint(3 downto 0)) + 1); ++ when "01" => watchpoint(7 downto 4) <= std_logic_vector(unsigned(watchpoint(7 downto 4)) + 1); ++ when "10" => watchpoint(11 downto 8) <= std_logic_vector(unsigned(watchpoint(11 downto 8)) + 1); ++ when "11" => watchpoint(15 downto 12) <= std_logic_vector(unsigned(watchpoint(15 downto 12)) + 1); ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end process; ++ ++ -- Set breakpoint address ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ breakpoint <= (others => '1'); ++ elsif rising_edge(CLOCK) and mode = modeBreak then ++ if r_set_n = '1' and nSET = '0' then ++ -- Increment selected digit on each button press ++ case digit is ++ when "00" => breakpoint(3 downto 0) <= std_logic_vector(unsigned(breakpoint(3 downto 0)) + 1); ++ when "01" => breakpoint(7 downto 4) <= std_logic_vector(unsigned(breakpoint(7 downto 4)) + 1); ++ when "10" => breakpoint(11 downto 8) <= std_logic_vector(unsigned(breakpoint(11 downto 8)) + 1); ++ when "11" => breakpoint(15 downto 12) <= std_logic_vector(unsigned(breakpoint(15 downto 12)) + 1); ++ ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end process; ++ ++ -- CPU control logic ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ r_step_n <= '1'; ++ halt <= '0'; ++ resuming <= '0'; ++ instr_addr <= (others => '0'); ++ elsif rising_edge(CLOCK) then ++ -- Register single-step button ++ r_step_n <= nSTEP; ++ ++ -- Once the CPU has run we can trigger a new halt ++ if CLKEN_IN = '1' then ++ resuming <= '0'; ++ end if; ++ ++ if SYNC = '1' then ++ -- Latch address of instruction fetch ++ instr_addr <= A_CPU; ++ end if; ++ ++ -- Check for halt conditions if we are not resuming from a previous halt ++ if resuming = '0' then ++ if RUN = '0' and SYNC = '1' then ++ -- If not in RUN mode then halt on any instruction fetch ++ -- (single-step) ++ halt <= '1'; ++ end if; ++ if A_CPU = breakpoint and SYNC = '1' then ++ -- Halt CPU when instruction fetched from breakpoint address ++ halt <= '1'; ++ end if; ++ if A_CPU = watchpoint and SYNC = '0' and R_nW = '0' then ++ -- Halt CPU when data write to watchpoint address ++ halt <= '1'; ++ end if; ++ end if; ++ ++ -- Resume or single step when user presses "STEP" button ++ if r_step_n = '1' and nSTEP = '0' then ++ resuming <= '1'; ++ halt <= '0'; ++ end if; ++ end if; ++ end process; ++end architecture; +diff --git a/i2c_loader.vhd b/i2c_loader.vhd +index 35da643..61bdd22 100644 +--- a/i2c_loader.vhd ++++ b/i2c_loader.vhd +@@ -1,304 +1,304 @@ +--- ZX Spectrum for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.STD_LOGIC_ARITH.ALL;
+-use IEEE.STD_LOGIC_UNSIGNED.ALL;
+-use IEEE.STD_LOGIC_MISC.ALL; -- for AND_REDUCE
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity i2c_loader is
+-generic (
+- -- Address of slave to be loaded
+- device_address : integer := 16#1a#;
+- -- Number of retries to allow before stopping
+- num_retries : integer := 0;
+- -- Length of clock divider in bits. Resulting bus frequency is
+- -- CLK/2^(log2_divider + 2)
+- log2_divider : integer := 6
+-);
+-
+-port (
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- I2C_SCL : inout std_logic;
+- I2C_SDA : inout std_logic;
+-
+- IS_DONE : out std_logic;
+- IS_ERROR : out std_logic
+- );
+-end i2c_loader;
+-
+-architecture i2c_loader_arch of i2c_loader is
+-type regs is array(0 to 19) of std_logic_vector(7 downto 0);
+-constant init_regs : regs := (
+- -- Left line in, 0dB, unmute
+- X"00", X"17",
+- -- Right line in, 0dB, unmute
+- X"02", X"17",
+- -- Left headphone out, 0dB
+- X"04", X"79",
+- -- Right headphone out, 0dB
+- X"06", X"79",
+- -- Audio path, DAC enabled, Line in, Bypass off, mic unmuted
+- X"08", X"10",
+- -- Digital path, Unmute, HP filter enabled
+- X"0A", X"00",
+- -- Power down mic, clkout and xtal osc
+- X"0C", X"62",
+- -- Format 16-bit I2S, no bit inversion or phase changes
+- X"0E", X"02",
+- -- Sampling control, 8 kHz USB mode (MCLK = 250fs * 6)
+- X"10", X"0D",
+- -- Activate
+- X"12", X"01"
+- );
+--- Number of bursts (i.e. total number of registers)
+-constant burst_length : positive := 2;
+--- Number of bytes to transfer per burst
+-constant num_bursts : positive := (init_regs'length / burst_length);
+-
+-type state_t is (Idle, Start, Data, Ack, Stop, Pause, Done);
+-signal state : state_t;
+-signal phase : std_logic_vector(1 downto 0);
+-subtype nbit_t is integer range 0 to 7;
+-signal nbit : nbit_t;
+-subtype nbyte_t is integer range 0 to burst_length; -- +1 for address byte
+-signal nbyte : nbyte_t;
+-subtype thisbyte_t is integer range 0 to init_regs'length; -- +1 for "done"
+-signal thisbyte : thisbyte_t;
+-subtype retries_t is integer range 0 to num_retries;
+-signal retries : retries_t;
+-
+-signal clken : std_logic;
+-signal divider : std_logic_vector(log2_divider-1 downto 0);
+-signal shiftreg : std_logic_vector(7 downto 0);
+-signal scl_out : std_logic;
+-signal sda_out : std_logic;
+-signal nak : std_logic;
+-begin
+- -- Create open-drain outputs for I2C bus
+- I2C_SCL <= '0' when scl_out = '0' else 'Z';
+- I2C_SDA <= '0' when sda_out = '0' else 'Z';
+- -- Status outputs are driven both ways
+- IS_DONE <= '1' when state = Done else '0';
+- IS_ERROR <= nak;
+-
+- -- Generate clock enable for desired bus speed
+- clken <= AND_REDUCE(divider);
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- divider <= (others => '0');
+- elsif falling_edge(CLK) then
+- divider <= divider + '1';
+- end if;
+- end process;
+-
+- -- The I2C loader process
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- scl_out <= '1';
+- sda_out <= '1';
+- state <= Idle;
+- phase <= "00";
+- nbit <= 0;
+- nbyte <= 0;
+- thisbyte <= 0;
+- shiftreg <= (others => '0');
+- nak <= '0'; -- No error
+- retries <= num_retries;
+- elsif rising_edge(CLK) and clken = '1' then
+- -- Next phase by default
+- phase <= phase + 1;
+-
+- -- STATE: IDLE
+- if state = Idle then
+- -- Start loading the device registers straight away
+- -- A 'GO' bit could be polled here if required
+- state <= Start;
+- phase <= "00";
+- scl_out <= '1';
+- sda_out <= '1';
+-
+- -- STATE: START
+- elsif state = Start then
+- -- Generate START condition
+- case phase is
+- when "00" =>
+- -- Drop SDA first
+- sda_out <= '0';
+- when "10" =>
+- -- Then drop SCL
+- scl_out <= '0';
+- when "11" =>
+- -- Advance to next state
+- -- Shift register loaded with device slave address
+- state <= Data;
+- nbit <= 7;
+- shiftreg <= std_logic_vector(to_unsigned(device_address,7)) & '0'; -- writing
+- nbyte <= burst_length;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: DATA
+- elsif state = Data then
+- -- Generate data
+- case phase is
+- when "00" =>
+- -- Drop SCL
+- scl_out <= '0';
+- when "01" =>
+- -- Output data and shift (MSb first)
+- sda_out <= shiftreg(7);
+- shiftreg <= shiftreg(6 downto 0) & '0';
+- when "10" =>
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- -- Next bit or advance to next state when done
+- if nbit = 0 then
+- state <= Ack;
+- else
+- nbit <= nbit - 1;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: ACK
+- elsif state = Ack then
+- -- Generate ACK clock and check for error condition
+- case phase is
+- when "00" =>
+- -- Drop SCL
+- scl_out <= '0';
+- when "01" =>
+- -- Float data
+- sda_out <= '1';
+- when "10" =>
+- -- Sample ack bit
+- nak <= I2C_SDA;
+- if I2C_SDA = '1' then
+- -- Error
+- nbyte <= 0; -- Close this burst and skip remaining registers
+- thisbyte <= init_regs'length;
+- else
+- -- Hold ACK to avoid spurious stops - this seems to fix a
+- -- problem with the Wolfson codec which releases the ACK
+- -- right on the falling edge of the clock pulse. It looks like
+- -- the device interprets this is a STOP condition and then fails
+- -- to acknowledge the next byte. We can avoid this by holding the
+- -- ACK condition for a little longer.
+- sda_out <= '0';
+- end if;
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- -- Advance to next state
+- if nbyte = 0 then
+- -- No more bytes in this burst - generate a STOP
+- state <= Stop;
+- else
+- -- Generate next byte
+- state <= Data;
+- nbit <= 7;
+- shiftreg <= init_regs(thisbyte);
+- nbyte <= nbyte - 1;
+- thisbyte <= thisbyte + 1;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: STOP
+- elsif state = Stop then
+- -- Generate STOP condition
+- case phase is
+- when "00" =>
+- -- Drop SCL first
+- scl_out <= '0';
+- when "01" =>
+- -- Drop SDA
+- sda_out <= '0';
+- when "10" =>
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- if thisbyte = init_regs'length then
+- -- All registers done, advance to finished state. This will
+- -- bring SDA high while SCL is still high, completing the STOP
+- -- condition
+- state <= Done;
+- else
+- -- Load the next register after a short delay
+- state <= Pause;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: PAUSE
+- elsif state = Pause then
+- -- Delay for one cycle of 'phase' then start the next burst
+- scl_out <= '1';
+- sda_out <= '1';
+- if phase = "11" then
+- state <= Start;
+- end if;
+-
+- -- STATE: DONE
+- else
+- -- Finished
+- scl_out <= '1';
+- sda_out <= '1';
+-
+- if nak = '1' and retries > 0 then
+- -- We can retry in the event of a NAK in case the
+- -- slave got out of sync for some reason
+- retries <= retries - 1;
+- state <= Idle;
+- end if;
+- end if;
+- end if;
+- end process;
+-end i2c_loader_arch;
+-
++-- ZX Spectrum for Altera DE1 ++-- ++-- Copyright (c) 2009-2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.STD_LOGIC_ARITH.ALL; ++use IEEE.STD_LOGIC_UNSIGNED.ALL; ++use IEEE.STD_LOGIC_MISC.ALL; -- for AND_REDUCE ++use IEEE.NUMERIC_STD.ALL; ++ ++entity i2c_loader is ++generic ( ++ -- Address of slave to be loaded ++ device_address : integer := 16#1a#; ++ -- Number of retries to allow before stopping ++ num_retries : integer := 0; ++ -- Length of clock divider in bits. Resulting bus frequency is ++ -- CLK/2^(log2_divider + 2) ++ log2_divider : integer := 6 ++); ++ ++port ( ++ CLK : in std_logic; ++ nRESET : in std_logic; ++ ++ I2C_SCL : inout std_logic; ++ I2C_SDA : inout std_logic; ++ ++ IS_DONE : out std_logic; ++ IS_ERROR : out std_logic ++ ); ++end i2c_loader; ++ ++architecture i2c_loader_arch of i2c_loader is ++type regs is array(0 to 19) of std_logic_vector(7 downto 0); ++constant init_regs : regs := ( ++ -- Left line in, 0dB, unmute ++ X"00", X"17", ++ -- Right line in, 0dB, unmute ++ X"02", X"17", ++ -- Left headphone out, 0dB ++ X"04", X"79", ++ -- Right headphone out, 0dB ++ X"06", X"79", ++ -- Audio path, DAC enabled, Line in, Bypass off, mic unmuted ++ X"08", X"10", ++ -- Digital path, Unmute, HP filter enabled ++ X"0A", X"00", ++ -- Power down mic, clkout and xtal osc ++ X"0C", X"62", ++ -- Format 16-bit I2S, no bit inversion or phase changes ++ X"0E", X"02", ++ -- Sampling control, 8 kHz USB mode (MCLK = 250fs * 6) ++ X"10", X"0D", ++ -- Activate ++ X"12", X"01" ++ ); ++-- Number of bursts (i.e. total number of registers) ++constant burst_length : positive := 2; ++-- Number of bytes to transfer per burst ++constant num_bursts : positive := (init_regs'length / burst_length); ++ ++type state_t is (Idle, Start, Data, Ack, Stop, Pause, Done); ++signal state : state_t; ++signal phase : std_logic_vector(1 downto 0); ++subtype nbit_t is integer range 0 to 7; ++signal nbit : nbit_t; ++subtype nbyte_t is integer range 0 to burst_length; -- +1 for address byte ++signal nbyte : nbyte_t; ++subtype thisbyte_t is integer range 0 to init_regs'length; -- +1 for "done" ++signal thisbyte : thisbyte_t; ++subtype retries_t is integer range 0 to num_retries; ++signal retries : retries_t; ++ ++signal clken : std_logic; ++signal divider : std_logic_vector(log2_divider-1 downto 0); ++signal shiftreg : std_logic_vector(7 downto 0); ++signal scl_out : std_logic; ++signal sda_out : std_logic; ++signal nak : std_logic; ++begin ++ -- Create open-drain outputs for I2C bus ++ I2C_SCL <= '0' when scl_out = '0' else 'Z'; ++ I2C_SDA <= '0' when sda_out = '0' else 'Z'; ++ -- Status outputs are driven both ways ++ IS_DONE <= '1' when state = Done else '0'; ++ IS_ERROR <= nak; ++ ++ -- Generate clock enable for desired bus speed ++ clken <= AND_REDUCE(divider); ++ process(nRESET,CLK) ++ begin ++ if nRESET = '0' then ++ divider <= (others => '0'); ++ elsif falling_edge(CLK) then ++ divider <= divider + '1'; ++ end if; ++ end process; ++ ++ -- The I2C loader process ++ process(nRESET,CLK) ++ begin ++ if nRESET = '0' then ++ scl_out <= '1'; ++ sda_out <= '1'; ++ state <= Idle; ++ phase <= "00"; ++ nbit <= 0; ++ nbyte <= 0; ++ thisbyte <= 0; ++ shiftreg <= (others => '0'); ++ nak <= '0'; -- No error ++ retries <= num_retries; ++ elsif rising_edge(CLK) and clken = '1' then ++ -- Next phase by default ++ phase <= phase + 1; ++ ++ -- STATE: IDLE ++ if state = Idle then ++ -- Start loading the device registers straight away ++ -- A 'GO' bit could be polled here if required ++ state <= Start; ++ phase <= "00"; ++ scl_out <= '1'; ++ sda_out <= '1'; ++ ++ -- STATE: START ++ elsif state = Start then ++ -- Generate START condition ++ case phase is ++ when "00" => ++ -- Drop SDA first ++ sda_out <= '0'; ++ when "10" => ++ -- Then drop SCL ++ scl_out <= '0'; ++ when "11" => ++ -- Advance to next state ++ -- Shift register loaded with device slave address ++ state <= Data; ++ nbit <= 7; ++ shiftreg <= std_logic_vector(to_unsigned(device_address,7)) & '0'; -- writing ++ nbyte <= burst_length; ++ when others => ++ null; ++ end case; ++ ++ -- STATE: DATA ++ elsif state = Data then ++ -- Generate data ++ case phase is ++ when "00" => ++ -- Drop SCL ++ scl_out <= '0'; ++ when "01" => ++ -- Output data and shift (MSb first) ++ sda_out <= shiftreg(7); ++ shiftreg <= shiftreg(6 downto 0) & '0'; ++ when "10" => ++ -- Raise SCL ++ scl_out <= '1'; ++ when "11" => ++ -- Next bit or advance to next state when done ++ if nbit = 0 then ++ state <= Ack; ++ else ++ nbit <= nbit - 1; ++ end if; ++ when others => ++ null; ++ end case; ++ ++ -- STATE: ACK ++ elsif state = Ack then ++ -- Generate ACK clock and check for error condition ++ case phase is ++ when "00" => ++ -- Drop SCL ++ scl_out <= '0'; ++ when "01" => ++ -- Float data ++ sda_out <= '1'; ++ when "10" => ++ -- Sample ack bit ++ nak <= I2C_SDA; ++ if I2C_SDA = '1' then ++ -- Error ++ nbyte <= 0; -- Close this burst and skip remaining registers ++ thisbyte <= init_regs'length; ++ else ++ -- Hold ACK to avoid spurious stops - this seems to fix a ++ -- problem with the Wolfson codec which releases the ACK ++ -- right on the falling edge of the clock pulse. It looks like ++ -- the device interprets this is a STOP condition and then fails ++ -- to acknowledge the next byte. We can avoid this by holding the ++ -- ACK condition for a little longer. ++ sda_out <= '0'; ++ end if; ++ -- Raise SCL ++ scl_out <= '1'; ++ when "11" => ++ -- Advance to next state ++ if nbyte = 0 then ++ -- No more bytes in this burst - generate a STOP ++ state <= Stop; ++ else ++ -- Generate next byte ++ state <= Data; ++ nbit <= 7; ++ shiftreg <= init_regs(thisbyte); ++ nbyte <= nbyte - 1; ++ thisbyte <= thisbyte + 1; ++ end if; ++ when others => ++ null; ++ end case; ++ ++ -- STATE: STOP ++ elsif state = Stop then ++ -- Generate STOP condition ++ case phase is ++ when "00" => ++ -- Drop SCL first ++ scl_out <= '0'; ++ when "01" => ++ -- Drop SDA ++ sda_out <= '0'; ++ when "10" => ++ -- Raise SCL ++ scl_out <= '1'; ++ when "11" => ++ if thisbyte = init_regs'length then ++ -- All registers done, advance to finished state. This will ++ -- bring SDA high while SCL is still high, completing the STOP ++ -- condition ++ state <= Done; ++ else ++ -- Load the next register after a short delay ++ state <= Pause; ++ end if; ++ when others => ++ null; ++ end case; ++ ++ -- STATE: PAUSE ++ elsif state = Pause then ++ -- Delay for one cycle of 'phase' then start the next burst ++ scl_out <= '1'; ++ sda_out <= '1'; ++ if phase = "11" then ++ state <= Start; ++ end if; ++ ++ -- STATE: DONE ++ else ++ -- Finished ++ scl_out <= '1'; ++ sda_out <= '1'; ++ ++ if nak = '1' and retries > 0 then ++ -- We can retry in the event of a NAK in case the ++ -- slave got out of sync for some reason ++ retries <= retries - 1; ++ state <= Idle; ++ end if; ++ end if; ++ end if; ++ end process; ++end i2c_loader_arch; ++ +diff --git a/i2s_intf.vhd b/i2s_intf.vhd +index e15ce2c..49b6efb 100644 +--- a/i2s_intf.vhd ++++ b/i2s_intf.vhd +@@ -1,37 +1,37 @@ + -- ZX Spectrum for Altera DE1 + -- +--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- Copyright (c) 2009-2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + -- POSSIBILITY OF SUCH DAMAGE. + -- + +diff --git a/keyboard.vhd b/keyboard.vhd +index c0b8603..cba4054 100644 +--- a/keyboard.vhd ++++ b/keyboard.vhd +@@ -1,294 +1,294 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC keyboard implementation with interface to PS/2
+---
+--- (C) 2011 Mike Stirling
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity keyboard is
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- CLKEN_1MHZ : in std_logic;
+-
+- -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- If 1 then column is incremented automatically at
+- -- 1 MHz rate
+- AUTOSCAN : in std_logic;
+-
+- COLUMN : in std_logic_vector(3 downto 0);
+- ROW : in std_logic_vector(2 downto 0);
+-
+- -- 1 when currently selected key is down (AUTOSCAN disabled)
+- KEYPRESS : out std_logic;
+- -- 1 when any key is down (except row 0)
+- INT : out std_logic;
+- -- BREAK key output - 1 when pressed
+- BREAK_OUT : out std_logic;
+-
+- -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of keyboard is
+-
+--- PS/2 interface
+-component ps2_intf is
+-generic (filter_length : positive := 8);
+-port(
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- PS/2 interface (could be bi-dir)
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- Byte-wide data interface - only valid for one clock
+- -- so must be latched externally if required
+- DATA : out std_logic_vector(7 downto 0);
+- VALID : out std_logic;
+- ERROR : out std_logic
+- );
+-end component;
+-
+--- Interface to PS/2 block
+-signal keyb_data : std_logic_vector(7 downto 0);
+-signal keyb_valid : std_logic;
+-signal keyb_error : std_logic;
+-
+--- Internal signals
+-type key_matrix is array(0 to 15) of std_logic_vector(7 downto 0);
+-signal keys : key_matrix;
+-signal col : unsigned(3 downto 0);
+-signal release : std_logic;
+-signal extended : std_logic;
+-begin
+-
+- ps2 : ps2_intf port map (
+- CLOCK, nRESET,
+- PS2_CLK, PS2_DATA,
+- keyb_data, keyb_valid, keyb_error
+- );
+-
+- -- Column counts automatically when AUTOSCAN is enabled, otherwise
+- -- value is loaded from external input
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- col <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- if AUTOSCAN = '0' then
+- -- If autoscan disabled then transfer current COLUMN to counter
+- -- immediately (don't wait for next 1 MHz cycle)
+- col <= unsigned(COLUMN);
+- elsif CLKEN_1MHZ = '1' then
+- -- Otherwise increment the counter once per 1 MHz tick
+- col <= col + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Generate interrupt if any key in currently scanned column is pressed
+- -- (apart from in row 0). Output selected key status if autoscan disabled.
+- process(keys,col,ROW,AUTOSCAN)
+- variable k : std_logic_vector(7 downto 0);
+- begin
+- -- Shortcut to current key column
+- k := keys(to_integer(col));
+-
+- -- Interrupt if any key pressed in rows 1 to 7.
+- INT <= k(7) or k(6) or k(5) or k(4) or k(3) or k(2) or k(1);
+-
+- -- Determine which key is pressed
+- -- Inhibit output during auto-scan
+- if AUTOSCAN = '0' then
+- KEYPRESS <= k(to_integer(unsigned(ROW)));
+- else
+- KEYPRESS <= '0';
+- end if;
+- end process;
+-
+- -- Decode PS/2 data
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- release <= '0';
+- extended <= '0';
+-
+- BREAK_OUT <= '0';
+-
+- keys(0) <= (others => '0');
+- keys(1) <= (others => '0');
+- keys(2) <= (others => '0');
+- keys(3) <= (others => '0');
+- keys(4) <= (others => '0');
+- keys(5) <= (others => '0');
+- keys(6) <= (others => '0');
+- keys(7) <= (others => '0');
+- keys(8) <= (others => '0');
+- keys(9) <= (others => '0');
+- -- These non-existent rows are used in the BBC master
+- keys(10) <= (others => '0');
+- keys(11) <= (others => '0');
+- keys(12) <= (others => '0');
+- keys(13) <= (others => '0');
+- keys(14) <= (others => '0');
+- keys(15) <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Copy DIP switches through to row 0
+- keys(2)(0) <= DIP_SWITCH(7);
+- keys(3)(0) <= DIP_SWITCH(6);
+- keys(4)(0) <= DIP_SWITCH(5);
+- keys(5)(0) <= DIP_SWITCH(4);
+- keys(6)(0) <= DIP_SWITCH(3);
+- keys(7)(0) <= DIP_SWITCH(2);
+- keys(8)(0) <= DIP_SWITCH(1);
+- keys(9)(0) <= DIP_SWITCH(0);
+-
+- if keyb_valid = '1' then
+- -- Decode keyboard input
+- if keyb_data = X"e0" then
+- -- Extended key code follows
+- extended <= '1';
+- elsif keyb_data = X"f0" then
+- -- Release code follows
+- release <= '1';
+- else
+- -- Cancel extended/release flags for next time
+- release <= '0';
+- extended <= '0';
+-
+- -- Decode scan codes
+- case keyb_data is
+- when X"12" => keys(0)(0) <= not release; -- Left SHIFT
+- when X"59" => keys(0)(0) <= not release; -- Right SHIFT
+- when X"15" => keys(0)(1) <= not release; -- Q
+- when X"09" => keys(0)(2) <= not release; -- F10 (F0)
+- when X"16" => keys(0)(3) <= not release; -- 1
+- when X"58" => keys(0)(4) <= not release; -- CAPS LOCK
+- when X"11" => keys(0)(5) <= not release; -- LEFT ALT (SHIFT LOCK)
+- when X"0D" => keys(0)(6) <= not release; -- TAB
+- when X"76" => keys(0)(7) <= not release; -- ESCAPE
+- when X"14" => keys(1)(0) <= not release; -- LEFT/RIGHT CTRL (CTRL)
+- when X"26" => keys(1)(1) <= not release; -- 3
+- when X"1D" => keys(1)(2) <= not release; -- W
+- when X"1E" => keys(1)(3) <= not release; -- 2
+- when X"1C" => keys(1)(4) <= not release; -- A
+- when X"1B" => keys(1)(5) <= not release; -- S
+- when X"1A" => keys(1)(6) <= not release; -- Z
+- when X"05" => keys(1)(7) <= not release; -- F1
+- when X"25" => keys(2)(1) <= not release; -- 4
+- when X"24" => keys(2)(2) <= not release; -- E
+- when X"23" => keys(2)(3) <= not release; -- D
+- when X"22" => keys(2)(4) <= not release; -- X
+- when X"21" => keys(2)(5) <= not release; -- C
+- when X"29" => keys(2)(6) <= not release; -- SPACE
+- when X"06" => keys(2)(7) <= not release; -- F2
+- when X"2E" => keys(3)(1) <= not release; -- 5
+- when X"2C" => keys(3)(2) <= not release; -- T
+- when X"2D" => keys(3)(3) <= not release; -- R
+- when X"2B" => keys(3)(4) <= not release; -- F
+- when X"34" => keys(3)(5) <= not release; -- G
+- when X"2A" => keys(3)(6) <= not release; -- V
+- when X"04" => keys(3)(7) <= not release; -- F3
+- when X"0C" => keys(4)(1) <= not release; -- F4
+- when X"3D" => keys(4)(2) <= not release; -- 7
+- when X"36" => keys(4)(3) <= not release; -- 6
+- when X"35" => keys(4)(4) <= not release; -- Y
+- when X"33" => keys(4)(5) <= not release; -- H
+- when X"32" => keys(4)(6) <= not release; -- B
+- when X"03" => keys(4)(7) <= not release; -- F5
+- when X"3E" => keys(5)(1) <= not release; -- 8
+- when X"43" => keys(5)(2) <= not release; -- I
+- when X"3C" => keys(5)(3) <= not release; -- U
+- when X"3B" => keys(5)(4) <= not release; -- J
+- when X"31" => keys(5)(5) <= not release; -- N
+- when X"3A" => keys(5)(6) <= not release; -- M
+- when X"0B" => keys(5)(7) <= not release; -- F6
+- when X"83" => keys(6)(1) <= not release; -- F7
+- when X"46" => keys(6)(2) <= not release; -- 9
+- when X"44" => keys(6)(3) <= not release; -- O
+- when X"42" => keys(6)(4) <= not release; -- K
+- when X"4B" => keys(6)(5) <= not release; -- L
+- when X"41" => keys(6)(6) <= not release; -- ,
+- when X"0A" => keys(6)(7) <= not release; -- F8
+- when X"4E" => keys(7)(1) <= not release; -- -
+- when X"45" => keys(7)(2) <= not release; -- 0
+- when X"4D" => keys(7)(3) <= not release; -- P
+- when X"0E" => keys(7)(4) <= not release; -- ` (@)
+- when X"4C" => keys(7)(5) <= not release; -- ;
+- when X"49" => keys(7)(6) <= not release; -- .
+- when X"01" => keys(7)(7) <= not release; -- F9
+- when X"55" => keys(8)(1) <= not release; -- = (^)
+- when X"5D" => keys(8)(2) <= not release; -- # (_)
+- when X"54" => keys(8)(3) <= not release; -- [
+- when X"52" => keys(8)(4) <= not release; -- '
+- when X"5B" => keys(8)(5) <= not release; -- ]
+- when X"4A" => keys(8)(6) <= not release; -- /
+- when X"61" => keys(8)(7) <= not release; -- \
+- when X"6B" => keys(9)(1) <= not release; -- LEFT
+- when X"72" => keys(9)(2) <= not release; -- DOWN
+- when X"75" => keys(9)(3) <= not release; -- UP
+- when X"5A" => keys(9)(4) <= not release; -- RETURN
+- when X"66" => keys(9)(5) <= not release; -- BACKSPACE (DELETE)
+- when X"69" => keys(9)(6) <= not release; -- END (COPY)
+- when X"74" => keys(9)(7) <= not release; -- RIGHT
+-
+- -- F12 is used for the BREAK key, which in the real BBC asserts
+- -- reset. Here we pass this out to the top level which may
+- -- optionally OR it in to the system reset
+- when X"07" => BREAK_OUT <= not release; -- F12 (BREAK)
+-
+- when others => null;
+- end case;
+-
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-end architecture;
+-
+-
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- BBC keyboard implementation with interface to PS/2 ++-- ++-- (C) 2011 Mike Stirling ++-- ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity keyboard is ++port ( ++ CLOCK : in std_logic; ++ nRESET : in std_logic; ++ CLKEN_1MHZ : in std_logic; ++ ++ -- PS/2 interface ++ PS2_CLK : in std_logic; ++ PS2_DATA : in std_logic; ++ ++ -- If 1 then column is incremented automatically at ++ -- 1 MHz rate ++ AUTOSCAN : in std_logic; ++ ++ COLUMN : in std_logic_vector(3 downto 0); ++ ROW : in std_logic_vector(2 downto 0); ++ ++ -- 1 when currently selected key is down (AUTOSCAN disabled) ++ KEYPRESS : out std_logic; ++ -- 1 when any key is down (except row 0) ++ INT : out std_logic; ++ -- BREAK key output - 1 when pressed ++ BREAK_OUT : out std_logic; ++ ++ -- DIP switch inputs ++ DIP_SWITCH : in std_logic_vector(7 downto 0) ++ ); ++end entity; ++ ++architecture rtl of keyboard is ++ ++-- PS/2 interface ++component ps2_intf is ++generic (filter_length : positive := 8); ++port( ++ CLK : in std_logic; ++ nRESET : in std_logic; ++ ++ -- PS/2 interface (could be bi-dir) ++ PS2_CLK : in std_logic; ++ PS2_DATA : in std_logic; ++ ++ -- Byte-wide data interface - only valid for one clock ++ -- so must be latched externally if required ++ DATA : out std_logic_vector(7 downto 0); ++ VALID : out std_logic; ++ ERROR : out std_logic ++ ); ++end component; ++ ++-- Interface to PS/2 block ++signal keyb_data : std_logic_vector(7 downto 0); ++signal keyb_valid : std_logic; ++signal keyb_error : std_logic; ++ ++-- Internal signals ++type key_matrix is array(0 to 15) of std_logic_vector(7 downto 0); ++signal keys : key_matrix; ++signal col : unsigned(3 downto 0); ++signal release : std_logic; ++signal extended : std_logic; ++begin ++ ++ ps2 : ps2_intf port map ( ++ CLOCK, nRESET, ++ PS2_CLK, PS2_DATA, ++ keyb_data, keyb_valid, keyb_error ++ ); ++ ++ -- Column counts automatically when AUTOSCAN is enabled, otherwise ++ -- value is loaded from external input ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ col <= (others => '0'); ++ elsif rising_edge(CLOCK) then ++ if AUTOSCAN = '0' then ++ -- If autoscan disabled then transfer current COLUMN to counter ++ -- immediately (don't wait for next 1 MHz cycle) ++ col <= unsigned(COLUMN); ++ elsif CLKEN_1MHZ = '1' then ++ -- Otherwise increment the counter once per 1 MHz tick ++ col <= col + 1; ++ end if; ++ end if; ++ end process; ++ ++ -- Generate interrupt if any key in currently scanned column is pressed ++ -- (apart from in row 0). Output selected key status if autoscan disabled. ++ process(keys,col,ROW,AUTOSCAN) ++ variable k : std_logic_vector(7 downto 0); ++ begin ++ -- Shortcut to current key column ++ k := keys(to_integer(col)); ++ ++ -- Interrupt if any key pressed in rows 1 to 7. ++ INT <= k(7) or k(6) or k(5) or k(4) or k(3) or k(2) or k(1); ++ ++ -- Determine which key is pressed ++ -- Inhibit output during auto-scan ++ if AUTOSCAN = '0' then ++ KEYPRESS <= k(to_integer(unsigned(ROW))); ++ else ++ KEYPRESS <= '0'; ++ end if; ++ end process; ++ ++ -- Decode PS/2 data ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ release <= '0'; ++ extended <= '0'; ++ ++ BREAK_OUT <= '0'; ++ ++ keys(0) <= (others => '0'); ++ keys(1) <= (others => '0'); ++ keys(2) <= (others => '0'); ++ keys(3) <= (others => '0'); ++ keys(4) <= (others => '0'); ++ keys(5) <= (others => '0'); ++ keys(6) <= (others => '0'); ++ keys(7) <= (others => '0'); ++ keys(8) <= (others => '0'); ++ keys(9) <= (others => '0'); ++ -- These non-existent rows are used in the BBC master ++ keys(10) <= (others => '0'); ++ keys(11) <= (others => '0'); ++ keys(12) <= (others => '0'); ++ keys(13) <= (others => '0'); ++ keys(14) <= (others => '0'); ++ keys(15) <= (others => '0'); ++ elsif rising_edge(CLOCK) then ++ -- Copy DIP switches through to row 0 ++ keys(2)(0) <= DIP_SWITCH(7); ++ keys(3)(0) <= DIP_SWITCH(6); ++ keys(4)(0) <= DIP_SWITCH(5); ++ keys(5)(0) <= DIP_SWITCH(4); ++ keys(6)(0) <= DIP_SWITCH(3); ++ keys(7)(0) <= DIP_SWITCH(2); ++ keys(8)(0) <= DIP_SWITCH(1); ++ keys(9)(0) <= DIP_SWITCH(0); ++ ++ if keyb_valid = '1' then ++ -- Decode keyboard input ++ if keyb_data = X"e0" then ++ -- Extended key code follows ++ extended <= '1'; ++ elsif keyb_data = X"f0" then ++ -- Release code follows ++ release <= '1'; ++ else ++ -- Cancel extended/release flags for next time ++ release <= '0'; ++ extended <= '0'; ++ ++ -- Decode scan codes ++ case keyb_data is ++ when X"12" => keys(0)(0) <= not release; -- Left SHIFT ++ when X"59" => keys(0)(0) <= not release; -- Right SHIFT ++ when X"15" => keys(0)(1) <= not release; -- Q ++ when X"09" => keys(0)(2) <= not release; -- F10 (F0) ++ when X"16" => keys(0)(3) <= not release; -- 1 ++ when X"58" => keys(0)(4) <= not release; -- CAPS LOCK ++ when X"11" => keys(0)(5) <= not release; -- LEFT ALT (SHIFT LOCK) ++ when X"0D" => keys(0)(6) <= not release; -- TAB ++ when X"76" => keys(0)(7) <= not release; -- ESCAPE ++ when X"14" => keys(1)(0) <= not release; -- LEFT/RIGHT CTRL (CTRL) ++ when X"26" => keys(1)(1) <= not release; -- 3 ++ when X"1D" => keys(1)(2) <= not release; -- W ++ when X"1E" => keys(1)(3) <= not release; -- 2 ++ when X"1C" => keys(1)(4) <= not release; -- A ++ when X"1B" => keys(1)(5) <= not release; -- S ++ when X"1A" => keys(1)(6) <= not release; -- Z ++ when X"05" => keys(1)(7) <= not release; -- F1 ++ when X"25" => keys(2)(1) <= not release; -- 4 ++ when X"24" => keys(2)(2) <= not release; -- E ++ when X"23" => keys(2)(3) <= not release; -- D ++ when X"22" => keys(2)(4) <= not release; -- X ++ when X"21" => keys(2)(5) <= not release; -- C ++ when X"29" => keys(2)(6) <= not release; -- SPACE ++ when X"06" => keys(2)(7) <= not release; -- F2 ++ when X"2E" => keys(3)(1) <= not release; -- 5 ++ when X"2C" => keys(3)(2) <= not release; -- T ++ when X"2D" => keys(3)(3) <= not release; -- R ++ when X"2B" => keys(3)(4) <= not release; -- F ++ when X"34" => keys(3)(5) <= not release; -- G ++ when X"2A" => keys(3)(6) <= not release; -- V ++ when X"04" => keys(3)(7) <= not release; -- F3 ++ when X"0C" => keys(4)(1) <= not release; -- F4 ++ when X"3D" => keys(4)(2) <= not release; -- 7 ++ when X"36" => keys(4)(3) <= not release; -- 6 ++ when X"35" => keys(4)(4) <= not release; -- Y ++ when X"33" => keys(4)(5) <= not release; -- H ++ when X"32" => keys(4)(6) <= not release; -- B ++ when X"03" => keys(4)(7) <= not release; -- F5 ++ when X"3E" => keys(5)(1) <= not release; -- 8 ++ when X"43" => keys(5)(2) <= not release; -- I ++ when X"3C" => keys(5)(3) <= not release; -- U ++ when X"3B" => keys(5)(4) <= not release; -- J ++ when X"31" => keys(5)(5) <= not release; -- N ++ when X"3A" => keys(5)(6) <= not release; -- M ++ when X"0B" => keys(5)(7) <= not release; -- F6 ++ when X"83" => keys(6)(1) <= not release; -- F7 ++ when X"46" => keys(6)(2) <= not release; -- 9 ++ when X"44" => keys(6)(3) <= not release; -- O ++ when X"42" => keys(6)(4) <= not release; -- K ++ when X"4B" => keys(6)(5) <= not release; -- L ++ when X"41" => keys(6)(6) <= not release; -- , ++ when X"0A" => keys(6)(7) <= not release; -- F8 ++ when X"4E" => keys(7)(1) <= not release; -- - ++ when X"45" => keys(7)(2) <= not release; -- 0 ++ when X"4D" => keys(7)(3) <= not release; -- P ++ when X"0E" => keys(7)(4) <= not release; -- ` (@) ++ when X"4C" => keys(7)(5) <= not release; -- ; ++ when X"49" => keys(7)(6) <= not release; -- . ++ when X"01" => keys(7)(7) <= not release; -- F9 ++ when X"55" => keys(8)(1) <= not release; -- = (^) ++ when X"5D" => keys(8)(2) <= not release; -- # (_) ++ when X"54" => keys(8)(3) <= not release; -- [ ++ when X"52" => keys(8)(4) <= not release; -- ' ++ when X"5B" => keys(8)(5) <= not release; -- ] ++ when X"4A" => keys(8)(6) <= not release; -- / ++ when X"61" => keys(8)(7) <= not release; -- \ ++ when X"6B" => keys(9)(1) <= not release; -- LEFT ++ when X"72" => keys(9)(2) <= not release; -- DOWN ++ when X"75" => keys(9)(3) <= not release; -- UP ++ when X"5A" => keys(9)(4) <= not release; -- RETURN ++ when X"66" => keys(9)(5) <= not release; -- BACKSPACE (DELETE) ++ when X"69" => keys(9)(6) <= not release; -- END (COPY) ++ when X"74" => keys(9)(7) <= not release; -- RIGHT ++ ++ -- F12 is used for the BREAK key, which in the real BBC asserts ++ -- reset. Here we pass this out to the top level which may ++ -- optionally OR it in to the system reset ++ when X"07" => BREAK_OUT <= not release; -- F12 (BREAK) ++ ++ when others => null; ++ end case; ++ ++ end if; ++ end if; ++ end if; ++ end process; ++ ++end architecture; ++ ++ +diff --git a/m6522.vhd b/m6522.vhd +index e01ed10..5c0d341 100644 +--- a/m6522.vhd ++++ b/m6522.vhd +@@ -1,886 +1,886 @@ +---
+--- A simulation model of VIC20 hardware
+--- Copyright (c) MikeJ - March 2003
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- You are responsible for any legal issues arising from your use of this code.
+---
+--- The latest version of this file can be found at: www.fpgaarcade.com
+---
+--- Email vic20@fpgaarcade.com
+---
+---
+--- Revision list
+---
+--- version 002 fix from Mark McDougall, untested
+--- version 001 initial release
+--- not very sure about the shift register, documentation is a bit light.
+-
+-library ieee ;
+- use ieee.std_logic_1164.all ;
+- use ieee.std_logic_unsigned.all;
+- use ieee.numeric_std.all;
+-
+---library UNISIM;
+--- use UNISIM.Vcomponents.all;
+-
+-entity M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable
+- CLK : in std_logic
+- );
+-end;
+-
+-architecture RTL of M6522 is
+-
+- signal phase : std_logic_vector(1 downto 0);
+- signal p2_h_t1 : std_logic;
+- signal cs : std_logic;
+-
+- -- registers
+- signal r_ddra : std_logic_vector(7 downto 0);
+- signal r_ora : std_logic_vector(7 downto 0);
+- signal r_ira : std_logic_vector(7 downto 0);
+-
+- signal r_ddrb : std_logic_vector(7 downto 0);
+- signal r_orb : std_logic_vector(7 downto 0);
+- signal r_irb : std_logic_vector(7 downto 0);
+-
+- signal r_t1l_l : std_logic_vector(7 downto 0);
+- signal r_t1l_h : std_logic_vector(7 downto 0);
+- signal r_t2l_l : std_logic_vector(7 downto 0);
+- signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip
+- signal r_sr : std_logic_vector(7 downto 0);
+- signal r_acr : std_logic_vector(7 downto 0);
+- signal r_pcr : std_logic_vector(7 downto 0);
+- signal r_ifr : std_logic_vector(7 downto 0);
+- signal r_ier : std_logic_vector(6 downto 0);
+-
+- signal sr_write_ena : boolean;
+- signal sr_read_ena : boolean;
+- signal ifr_write_ena : boolean;
+- signal ier_write_ena : boolean;
+- signal clear_irq : std_logic_vector(7 downto 0);
+- signal load_data : std_logic_vector(7 downto 0);
+-
+- -- timer 1
+- signal t1c : std_logic_vector(15 downto 0);
+- signal t1c_active : boolean;
+- signal t1c_done : boolean;
+- signal t1_w_reset_int : boolean;
+- signal t1_r_reset_int : boolean;
+- signal t1_load_counter : boolean;
+- signal t1_reload_counter : boolean;
+- signal t1_toggle : std_logic;
+- signal t1_irq : std_logic := '0';
+-
+- -- timer 2
+- signal t2c : std_logic_vector(15 downto 0);
+- signal t2c_active : boolean;
+- signal t2c_done : boolean;
+- signal t2_pb6 : std_logic;
+- signal t2_pb6_t1 : std_logic;
+- signal t2_w_reset_int : boolean;
+- signal t2_r_reset_int : boolean;
+- signal t2_load_counter : boolean;
+- signal t2_reload_counter : boolean;
+- signal t2_irq : std_logic := '0';
+- signal t2_sr_ena : boolean;
+-
+- -- shift reg
+- signal sr_cnt : std_logic_vector(3 downto 0);
+- signal sr_cb1_oe_l : std_logic;
+- signal sr_cb1_out : std_logic;
+- signal sr_drive_cb2 : std_logic;
+- signal sr_strobe : std_logic;
+- signal sr_strobe_t1 : std_logic;
+- signal sr_strobe_falling : boolean;
+- signal sr_strobe_rising : boolean;
+- signal sr_irq : std_logic;
+- signal sr_out : std_logic;
+- signal sr_off_delay : std_logic;
+-
+- -- io
+- signal w_orb_hs : std_logic;
+- signal w_ora_hs : std_logic;
+- signal r_irb_hs : std_logic;
+- signal r_ira_hs : std_logic;
+-
+- signal ca_hs_sr : std_logic;
+- signal ca_hs_pulse : std_logic;
+- signal cb_hs_sr : std_logic;
+- signal cb_hs_pulse : std_logic;
+-
+- signal cb1_in_mux : std_logic;
+- signal ca1_ip_reg : std_logic;
+- signal cb1_ip_reg : std_logic;
+- signal ca1_int : boolean;
+- signal cb1_int : boolean;
+- signal ca1_irq : std_logic;
+- signal cb1_irq : std_logic;
+-
+- signal ca2_ip_reg : std_logic;
+- signal cb2_ip_reg : std_logic;
+- signal ca2_int : boolean;
+- signal cb2_int : boolean;
+- signal ca2_irq : std_logic;
+- signal cb2_irq : std_logic;
+-
+- signal final_irq : std_logic;
+-begin
+- p_phase : process
+- begin
+- -- internal clock phase
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- p2_h_t1 <= I_P2_H;
+- if (p2_h_t1 = '0') and (I_P2_H = '1') then
+- phase <= "11";
+- else
+- phase <= phase + "1";
+- end if;
+- end if;
+- end process;
+-
+- p_cs : process(I_CS1, I_CS2_L, I_P2_H)
+- begin
+- cs <= '0';
+- if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
+- cs <= '1';
+- end if;
+- end process;
+-
+- -- peripheral control reg (pcr)
+- -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
+- -- 3..1 ca2 operation
+- -- 000 input -ve edge
+- -- 001 independend interrupt input -ve edge
+- -- 010 input +ve edge
+- -- 011 independend interrupt input +ve edge
+- -- 100 handshake output
+- -- 101 pulse output
+- -- 110 low output
+- -- 111 high output
+- -- 7..4 as 3..0 for cb1,cb2
+-
+- -- auxiliary control reg (acr)
+- -- 0 input latch PA (0 disable, 1 enable)
+- -- 1 input latch PB (0 disable, 1 enable)
+- -- 4..2 shift reg control
+- -- 000 disable
+- -- 001 shift in using t2
+- -- 010 shift in using o2
+- -- 011 shift in using ext clk
+- -- 100 shift out free running t2 rate
+- -- 101 shift out using t2
+- -- 101 shift out using o2
+- -- 101 shift out using ext clk
+- -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
+- -- 7..6 t1 timer control
+- -- 00 timed interrupt each time t1 is loaded pb7 disable
+- -- 01 continuous interrupts pb7 disable
+- -- 00 timed interrupt each time t1 is loaded pb7 one shot output
+- -- 01 continuous interrupts pb7 square wave output
+- --
+-
+- p_write_reg_reset : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- r_ora <= x"00"; r_orb <= x"00";
+- r_ddra <= x"00"; r_ddrb <= x"00";
+- r_acr <= x"00"; r_pcr <= x"00";
+-
+- w_orb_hs <= '0';
+- w_ora_hs <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- w_orb_hs <= '0';
+- w_ora_hs <= '0';
+- if (cs = '1') and (I_RW_L = '0') then
+- case I_RS is
+- when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
+- when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
+- when x"2" => r_ddrb <= I_DATA;
+- when x"3" => r_ddra <= I_DATA;
+-
+- when x"B" => r_acr <= I_DATA;
+- when x"C" => r_pcr <= I_DATA;
+- when x"F" => r_ora <= I_DATA;
+-
+- when others => null;
+- end case;
+- end if;
+-
+- if (r_acr(7) = '1') and (t1_toggle = '1') then
+- r_orb(7) <= not r_orb(7); -- toggle
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_write_reg : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- t1_w_reset_int <= false;
+- t1_load_counter <= false;
+-
+- t2_w_reset_int <= false;
+- t2_load_counter <= false;
+-
+- load_data <= x"00";
+- sr_write_ena <= false;
+- ifr_write_ena <= false;
+- ier_write_ena <= false;
+-
+- if (cs = '1') and (I_RW_L = '0') then
+- load_data <= I_DATA;
+- case I_RS is
+- when x"4" => r_t1l_l <= I_DATA;
+- when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+- t1_load_counter <= true;
+-
+- when x"6" => r_t1l_l <= I_DATA;
+- when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+-
+- when x"8" => r_t2l_l <= I_DATA;
+- when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
+- t2_load_counter <= true;
+-
+- when x"A" => sr_write_ena <= true;
+- when x"D" => ifr_write_ena <= true;
+- when x"E" => ier_write_ena <= true;
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- p_oe : process(cs, I_RW_L)
+- begin
+- O_DATA_OE_L <= '1';
+- if (cs = '1') and (I_RW_L = '1') then
+- O_DATA_OE_L <= '0';
+- end if;
+- end process;
+-
+- p_read : process
+- begin
+- wait until rising_edge(CLK);
+-
+- if ENA_4 = '1' then
+- t1_r_reset_int <= false;
+- t2_r_reset_int <= false;
+- sr_read_ena <= false;
+- r_irb_hs <= '0';
+- r_ira_hs <= '0';
+-
+- if (cs = '1') and (I_RW_L = '1') then
+- case I_RS is
+- --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
+- -- fix from Mark McDougall, untested
+- when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
+- when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
+- when x"2" => O_DATA <= r_ddrb;
+- when x"3" => O_DATA <= r_ddra;
+- when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
+- when x"5" => O_DATA <= t1c(15 downto 8);
+- when x"6" => O_DATA <= r_t1l_l;
+- when x"7" => O_DATA <= r_t1l_h;
+- when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
+- when x"9" => O_DATA <= t2c(15 downto 8);
+- when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
+- when x"B" => O_DATA <= r_acr;
+- when x"C" => O_DATA <= r_pcr;
+- when x"D" => O_DATA <= r_ifr;
+- when x"E" => O_DATA <= ('0' & r_ier);
+- when x"F" => O_DATA <= r_ira;
+- when others => null;
+- end case;
+- end if;
+- end if;
+-
+- end process;
+- --
+- -- IO
+- --
+- p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
+- begin
+- -- if the shift register is enabled, cb1 may be an output
+- -- in this case, we should listen to the CB1_OUT for the interrupt
+- if (sr_cb1_oe_l = '1') then
+- cb1_in_mux <= I_CB1;
+- else
+- cb1_in_mux <= sr_cb1_out;
+- end if;
+- end process;
+-
+- p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
+- begin
+- if (r_pcr(0) = '0') then -- ca1 control
+- -- negative edge
+- ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
+- else
+- -- positive edge
+- ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
+- end if;
+-
+- if (r_pcr(4) = '0') then -- cb1 control
+- -- negative edge
+- cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
+- else
+- -- positive edge
+- cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
+- end if;
+- end process;
+-
+- p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
+- begin
+- ca2_int <= false;
+- if (r_pcr(3) = '0') then -- ca2 input
+- if (r_pcr(2) = '0') then -- ca2 edge
+- -- negative edge
+- ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
+- else
+- -- positive edge
+- ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
+- end if;
+- end if;
+-
+- cb2_int <= false;
+- if (r_pcr(7) = '0') then -- cb2 input
+- if (r_pcr(6) = '0') then -- cb2 edge
+- -- negative edge
+- cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
+- else
+- -- positive edge
+- cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
+- end if;
+- end if;
+- end process;
+-
+- p_ca2_cb2 : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- O_CA2 <= '0';
+- O_CA2_OE_L <= '1';
+- O_CB2 <= '0';
+- O_CB2_OE_L <= '1';
+-
+- ca_hs_sr <= '0';
+- ca_hs_pulse <= '0';
+- cb_hs_sr <= '0';
+- cb_hs_pulse <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- ca
+- if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
+- ca_hs_sr <= '1';
+- elsif ca1_int then
+- ca_hs_sr <= '0';
+- end if;
+-
+- if (phase = "00") then
+- ca_hs_pulse <= w_ora_hs or r_ira_hs;
+- end if;
+-
+- O_CA2_OE_L <= not r_pcr(3); -- ca2 output
+- case r_pcr(3 downto 1) is
+- when "000" => O_CA2 <= '0'; -- input
+- when "001" => O_CA2 <= '0'; -- input
+- when "010" => O_CA2 <= '0'; -- input
+- when "011" => O_CA2 <= '0'; -- input
+- when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
+- when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
+- when "110" => O_CA2 <= '0'; -- low
+- when "111" => O_CA2 <= '1'; -- high
+- when others => null;
+- end case;
+-
+- -- cb
+- if (phase = "00") and (w_orb_hs = '1') then
+- cb_hs_sr <= '1';
+- elsif cb1_int then
+- cb_hs_sr <= '0';
+- end if;
+-
+- if (phase = "00") then
+- cb_hs_pulse <= w_orb_hs;
+- end if;
+-
+- O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
+- if (sr_drive_cb2 = '1') then -- serial output
+- O_CB2 <= sr_out;
+- else
+- case r_pcr(7 downto 5) is
+- when "000" => O_CB2 <= '0'; -- input
+- when "001" => O_CB2 <= '0'; -- input
+- when "010" => O_CB2 <= '0'; -- input
+- when "011" => O_CB2 <= '0'; -- input
+- when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
+- when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
+- when "110" => O_CB2 <= '0'; -- low
+- when "111" => O_CB2 <= '1'; -- high
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end process;
+- O_CB1 <= sr_cb1_out;
+- O_CB1_OE_L <= sr_cb1_oe_l;
+-
+- p_ca_cb_irq : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- ca1_irq <= '0';
+- ca2_irq <= '0';
+- cb1_irq <= '0';
+- cb2_irq <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- not pretty
+- if ca1_int then
+- ca1_irq <= '1';
+- elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
+- ca1_irq <= '0';
+- end if;
+-
+- if ca2_int then
+- ca2_irq <= '1';
+- else
+- if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
+- (clear_irq(0) = '1') then
+- ca2_irq <= '0';
+- end if;
+- end if;
+-
+- if cb1_int then
+- cb1_irq <= '1';
+- elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
+- cb1_irq <= '0';
+- end if;
+-
+- if cb2_int then
+- cb2_irq <= '1';
+- else
+- if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
+- (clear_irq(3) = '1') then
+- cb2_irq <= '0';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_input_reg : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- ca1_ip_reg <= '0';
+- cb1_ip_reg <= '0';
+-
+- ca2_ip_reg <= '0';
+- cb2_ip_reg <= '0';
+-
+- r_ira <= x"00";
+- r_irb <= x"00";
+-
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- we have a fast clock, so we can have input registers
+- ca1_ip_reg <= I_CA1;
+- cb1_ip_reg <= cb1_in_mux;
+-
+- ca2_ip_reg <= I_CA2;
+- cb2_ip_reg <= I_CB2;
+-
+- if (r_acr(0) = '0') then
+- r_ira <= I_PA;
+- else -- enable latching
+- if ca1_int then
+- r_ira <= I_PA;
+- end if;
+- end if;
+-
+- if (r_acr(1) = '0') then
+- r_irb <= I_PB;
+- else -- enable latching
+- if cb1_int then
+- r_irb <= I_PB;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-
+- p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
+- begin
+- -- data direction reg (ddr) 0 = input, 1 = output
+- O_PA <= r_ora;
+- O_PA_OE_L <= not r_ddra;
+-
+- if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
+- O_PB_OE_L(7) <= '0'; -- an output if under t1 control
+- else
+- O_PB_OE_L(7) <= not (r_ddrb(7));
+- end if;
+-
+- O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
+- O_PB(7 downto 0) <= r_orb(7 downto 0);
+-
+- end process;
+- --
+- -- Timer 1
+- --
+- p_timer1_done : process(t1c,phase,r_acr)
+- variable done : boolean;
+- begin
+- done := (t1c = x"0000");
+- t1c_done <= done and (phase = "11");
+- --if (phase = "11") then
+- t1_reload_counter <= done and (r_acr(6) = '1');
+- --end if;
+- end process;
+-
+- p_timer1 : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if t1_load_counter or (t1_reload_counter and phase = "11") then
+- t1c( 7 downto 0) <= r_t1l_l;
+- t1c(15 downto 8) <= r_t1l_h;
+- elsif (phase="11") then
+- t1c <= t1c - "1";
+- end if;
+-
+- if t1_load_counter or t1_reload_counter then
+- t1c_active <= true;
+- elsif t1c_done then
+- t1c_active <= false;
+- end if;
+- if RESET_L = '0' then
+- t1c_active <= false;
+- end if;
+-
+- t1_toggle <= '0';
+- if t1c_active and t1c_done then
+- t1_toggle <= '1';
+- t1_irq <= '1';
+- elsif RESET_L = '0' or t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
+- t1_irq <= '0';
+- end if;
+- end if;
+- end process;
+- --
+- -- Timer2
+- --
+- p_timer2_pb6_input : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if (phase = "01") then -- leading edge p2_h
+- t2_pb6 <= I_PB(6);
+- t2_pb6_t1 <= t2_pb6;
+- end if;
+- end if;
+- end process;
+-
+- p_timer2_done : process(t2c,phase)
+- variable done : boolean;
+- begin
+- done := (t2c = x"0000");
+- t2c_done <= done and (phase = "11");
+- --if (phase = "11") then
+- t2_reload_counter <= done;
+- --end if;
+- end process;
+-
+- p_timer2 : process
+- variable ena : boolean;
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if (r_acr(5) = '0') then
+- ena := true;
+- else
+- ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
+- end if;
+-
+- if t2_load_counter or (t2_reload_counter and phase = "11") then
+- -- not sure if t2c_reload should be here. Does timer2 just continue to
+- -- count down, or is it reloaded ? Reloaded makes more sense if using
+- -- it to generate a clock for the shift register.
+- t2c( 7 downto 0) <= r_t2l_l;
+- t2c(15 downto 8) <= r_t2l_h;
+- else
+- if (phase="11") and ena then -- or count mode
+- t2c <= t2c - "1";
+- end if;
+- end if;
+-
+- t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
+-
+- if t2_load_counter then
+- t2c_active <= true;
+- elsif t2c_done then
+- t2c_active <= false;
+- end if;
+- if RESET_L = '0' then
+- t2c_active <= false;
+- end if;
+-
+- if t2c_active and t2c_done then
+- t2_irq <= '1';
+- elsif RESET_L = '0' or t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
+- t2_irq <= '0';
+- end if;
+- end if;
+- end process;
+- --
+- -- Shift Register
+- --
+- p_sr : process(RESET_L, CLK)
+- variable dir_out : std_logic;
+- variable ena : std_logic;
+- variable cb1_op : std_logic;
+- variable cb1_ip : std_logic;
+- variable use_t2 : std_logic;
+- variable free_run : std_logic;
+- variable sr_count_ena : boolean;
+- begin
+- if (RESET_L = '0') then
+- r_sr <= x"00";
+- sr_drive_cb2 <= '0';
+- sr_cb1_oe_l <= '1';
+- sr_cb1_out <= '0';
+- sr_strobe <= '1';
+- sr_cnt <= "0000";
+- sr_irq <= '0';
+- sr_out <= '1';
+- sr_off_delay <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- decode mode
+- dir_out := r_acr(4); -- output on cb2
+- cb1_op := '0';
+- cb1_ip := '0';
+- use_t2 := '0';
+- free_run := '0';
+-
+- case r_acr(4 downto 2) is
+- when "000" => ena := '0'; cb1_ip := '1';
+- when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+- when "010" => ena := '1'; cb1_op := '1';
+- when "011" => ena := '1'; cb1_ip := '1';
+- when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
+- when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+- when "110" => ena := '1';
+- when "111" => ena := '1'; cb1_ip := '1';
+- when others => null;
+- end case;
+-
+- -- clock select
+- -- SR still runs even in disabled mode (on rising edge of CB1). It
+- -- just doesn't generate any interrupts.
+- -- Ref BBC micro advanced user guide p409
+- if (cb1_ip = '1') then
+- sr_strobe <= I_CB1;
+- else
+- if (sr_cnt(3) = '0') and (free_run = '0') then
+- sr_strobe <= '1';
+- else
+- if ((use_t2 = '1') and t2_sr_ena) or
+- ((use_t2 = '0') and (phase = "00")) then
+- sr_strobe <= not sr_strobe;
+- end if;
+- end if;
+- end if;
+-
+- -- latch on rising edge, shift on falling edge
+- if sr_write_ena then
+- r_sr <= load_data;
+- else
+- if (dir_out = '0') then
+- -- input
+- if (sr_cnt(3) = '1') or (cb1_ip = '1') then
+- if sr_strobe_rising then
+- r_sr <= r_sr(6 downto 0) & I_CB2;
+- end if;
+- end if;
+- sr_out <= '1';
+- else
+- -- output
+- if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
+- if sr_strobe_falling then
+- r_sr(7 downto 1) <= r_sr(6 downto 0);
+- r_sr(0) <= r_sr(7);
+- sr_out <= r_sr(7);
+- end if;
+- else
+- sr_out <= '1';
+- end if;
+- end if;
+- end if;
+-
+- sr_count_ena := sr_strobe_rising;
+-
+- if sr_write_ena or sr_read_ena then
+- -- some documentation says sr bit in IFR must be set as well ?
+- sr_cnt <= "1000";
+- elsif sr_count_ena and (sr_cnt(3) = '1') then
+- sr_cnt <= sr_cnt + "1";
+- end if;
+-
+- if (phase = "00") then
+- sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
+- end if;
+-
+- if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
+- sr_irq <= '1';
+- elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
+- sr_irq <= '0';
+- end if;
+-
+- -- assign ops
+- sr_drive_cb2 <= dir_out;
+- sr_cb1_oe_l <= not cb1_op;
+- sr_cb1_out <= sr_strobe;
+- end if;
+- end if;
+- end process;
+-
+- p_sr_strobe_rise_fall : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- sr_strobe_t1 <= sr_strobe;
+- sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
+- sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
+- end if;
+- end process;
+- --
+- -- Interrupts
+- --
+- p_ier : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- r_ier <= "0000000";
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- if ier_write_ena then
+- if (load_data(7) = '1') then
+- -- set
+- r_ier <= r_ier or load_data(6 downto 0);
+- else
+- -- clear
+- r_ier <= r_ier and not load_data(6 downto 0);
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
+- cb1_irq, cb2_irq)
+- begin
+- r_ifr(7) <= final_irq;
+- r_ifr(6) <= t1_irq;
+- r_ifr(5) <= t2_irq;
+- r_ifr(4) <= cb1_irq;
+- r_ifr(3) <= cb2_irq;
+- r_ifr(2) <= sr_irq;
+- r_ifr(1) <= ca1_irq;
+- r_ifr(0) <= ca2_irq;
+-
+- O_IRQ_L <= not final_irq;
+- end process;
+-
+- p_irq : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- final_irq <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
+- final_irq <= '0'; -- no interrupts
+- else
+- final_irq <= '1';
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_clear_irq : process(ifr_write_ena, load_data)
+- begin
+- clear_irq <= x"00";
+- if ifr_write_ena then
+- clear_irq <= load_data;
+- end if;
+- end process;
+-
+-end architecture RTL;
++-- ++-- A simulation model of VIC20 hardware ++-- Copyright (c) MikeJ - March 2003 ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written permission. ++-- ++-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- You are responsible for any legal issues arising from your use of this code. ++-- ++-- The latest version of this file can be found at: www.fpgaarcade.com ++-- ++-- Email vic20@fpgaarcade.com ++-- ++-- ++-- Revision list ++-- ++-- version 002 fix from Mark McDougall, untested ++-- version 001 initial release ++-- not very sure about the shift register, documentation is a bit light. ++ ++library ieee ; ++ use ieee.std_logic_1164.all ; ++ use ieee.std_logic_unsigned.all; ++ use ieee.numeric_std.all; ++ ++--library UNISIM; ++-- use UNISIM.Vcomponents.all; ++ ++entity M6522 is ++ port ( ++ ++ I_RS : in std_logic_vector(3 downto 0); ++ I_DATA : in std_logic_vector(7 downto 0); ++ O_DATA : out std_logic_vector(7 downto 0); ++ O_DATA_OE_L : out std_logic; ++ ++ I_RW_L : in std_logic; ++ I_CS1 : in std_logic; ++ I_CS2_L : in std_logic; ++ ++ O_IRQ_L : out std_logic; -- note, not open drain ++ -- port a ++ I_CA1 : in std_logic; ++ I_CA2 : in std_logic; ++ O_CA2 : out std_logic; ++ O_CA2_OE_L : out std_logic; ++ ++ I_PA : in std_logic_vector(7 downto 0); ++ O_PA : out std_logic_vector(7 downto 0); ++ O_PA_OE_L : out std_logic_vector(7 downto 0); ++ ++ -- port b ++ I_CB1 : in std_logic; ++ O_CB1 : out std_logic; ++ O_CB1_OE_L : out std_logic; ++ ++ I_CB2 : in std_logic; ++ O_CB2 : out std_logic; ++ O_CB2_OE_L : out std_logic; ++ ++ I_PB : in std_logic_vector(7 downto 0); ++ O_PB : out std_logic_vector(7 downto 0); ++ O_PB_OE_L : out std_logic_vector(7 downto 0); ++ ++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__ ++ RESET_L : in std_logic; ++ ENA_4 : in std_logic; -- clk enable ++ CLK : in std_logic ++ ); ++end; ++ ++architecture RTL of M6522 is ++ ++ signal phase : std_logic_vector(1 downto 0); ++ signal p2_h_t1 : std_logic; ++ signal cs : std_logic; ++ ++ -- registers ++ signal r_ddra : std_logic_vector(7 downto 0); ++ signal r_ora : std_logic_vector(7 downto 0); ++ signal r_ira : std_logic_vector(7 downto 0); ++ ++ signal r_ddrb : std_logic_vector(7 downto 0); ++ signal r_orb : std_logic_vector(7 downto 0); ++ signal r_irb : std_logic_vector(7 downto 0); ++ ++ signal r_t1l_l : std_logic_vector(7 downto 0); ++ signal r_t1l_h : std_logic_vector(7 downto 0); ++ signal r_t2l_l : std_logic_vector(7 downto 0); ++ signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip ++ signal r_sr : std_logic_vector(7 downto 0); ++ signal r_acr : std_logic_vector(7 downto 0); ++ signal r_pcr : std_logic_vector(7 downto 0); ++ signal r_ifr : std_logic_vector(7 downto 0); ++ signal r_ier : std_logic_vector(6 downto 0); ++ ++ signal sr_write_ena : boolean; ++ signal sr_read_ena : boolean; ++ signal ifr_write_ena : boolean; ++ signal ier_write_ena : boolean; ++ signal clear_irq : std_logic_vector(7 downto 0); ++ signal load_data : std_logic_vector(7 downto 0); ++ ++ -- timer 1 ++ signal t1c : std_logic_vector(15 downto 0); ++ signal t1c_active : boolean; ++ signal t1c_done : boolean; ++ signal t1_w_reset_int : boolean; ++ signal t1_r_reset_int : boolean; ++ signal t1_load_counter : boolean; ++ signal t1_reload_counter : boolean; ++ signal t1_toggle : std_logic; ++ signal t1_irq : std_logic := '0'; ++ ++ -- timer 2 ++ signal t2c : std_logic_vector(15 downto 0); ++ signal t2c_active : boolean; ++ signal t2c_done : boolean; ++ signal t2_pb6 : std_logic; ++ signal t2_pb6_t1 : std_logic; ++ signal t2_w_reset_int : boolean; ++ signal t2_r_reset_int : boolean; ++ signal t2_load_counter : boolean; ++ signal t2_reload_counter : boolean; ++ signal t2_irq : std_logic := '0'; ++ signal t2_sr_ena : boolean; ++ ++ -- shift reg ++ signal sr_cnt : std_logic_vector(3 downto 0); ++ signal sr_cb1_oe_l : std_logic; ++ signal sr_cb1_out : std_logic; ++ signal sr_drive_cb2 : std_logic; ++ signal sr_strobe : std_logic; ++ signal sr_strobe_t1 : std_logic; ++ signal sr_strobe_falling : boolean; ++ signal sr_strobe_rising : boolean; ++ signal sr_irq : std_logic; ++ signal sr_out : std_logic; ++ signal sr_off_delay : std_logic; ++ ++ -- io ++ signal w_orb_hs : std_logic; ++ signal w_ora_hs : std_logic; ++ signal r_irb_hs : std_logic; ++ signal r_ira_hs : std_logic; ++ ++ signal ca_hs_sr : std_logic; ++ signal ca_hs_pulse : std_logic; ++ signal cb_hs_sr : std_logic; ++ signal cb_hs_pulse : std_logic; ++ ++ signal cb1_in_mux : std_logic; ++ signal ca1_ip_reg : std_logic; ++ signal cb1_ip_reg : std_logic; ++ signal ca1_int : boolean; ++ signal cb1_int : boolean; ++ signal ca1_irq : std_logic; ++ signal cb1_irq : std_logic; ++ ++ signal ca2_ip_reg : std_logic; ++ signal cb2_ip_reg : std_logic; ++ signal ca2_int : boolean; ++ signal cb2_int : boolean; ++ signal ca2_irq : std_logic; ++ signal cb2_irq : std_logic; ++ ++ signal final_irq : std_logic; ++begin ++ p_phase : process ++ begin ++ -- internal clock phase ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ p2_h_t1 <= I_P2_H; ++ if (p2_h_t1 = '0') and (I_P2_H = '1') then ++ phase <= "11"; ++ else ++ phase <= phase + "1"; ++ end if; ++ end if; ++ end process; ++ ++ p_cs : process(I_CS1, I_CS2_L, I_P2_H) ++ begin ++ cs <= '0'; ++ if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then ++ cs <= '1'; ++ end if; ++ end process; ++ ++ -- peripheral control reg (pcr) ++ -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge) ++ -- 3..1 ca2 operation ++ -- 000 input -ve edge ++ -- 001 independend interrupt input -ve edge ++ -- 010 input +ve edge ++ -- 011 independend interrupt input +ve edge ++ -- 100 handshake output ++ -- 101 pulse output ++ -- 110 low output ++ -- 111 high output ++ -- 7..4 as 3..0 for cb1,cb2 ++ ++ -- auxiliary control reg (acr) ++ -- 0 input latch PA (0 disable, 1 enable) ++ -- 1 input latch PB (0 disable, 1 enable) ++ -- 4..2 shift reg control ++ -- 000 disable ++ -- 001 shift in using t2 ++ -- 010 shift in using o2 ++ -- 011 shift in using ext clk ++ -- 100 shift out free running t2 rate ++ -- 101 shift out using t2 ++ -- 101 shift out using o2 ++ -- 101 shift out using ext clk ++ -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6) ++ -- 7..6 t1 timer control ++ -- 00 timed interrupt each time t1 is loaded pb7 disable ++ -- 01 continuous interrupts pb7 disable ++ -- 00 timed interrupt each time t1 is loaded pb7 one shot output ++ -- 01 continuous interrupts pb7 square wave output ++ -- ++ ++ p_write_reg_reset : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ r_ora <= x"00"; r_orb <= x"00"; ++ r_ddra <= x"00"; r_ddrb <= x"00"; ++ r_acr <= x"00"; r_pcr <= x"00"; ++ ++ w_orb_hs <= '0'; ++ w_ora_hs <= '0'; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ w_orb_hs <= '0'; ++ w_ora_hs <= '0'; ++ if (cs = '1') and (I_RW_L = '0') then ++ case I_RS is ++ when x"0" => r_orb <= I_DATA; w_orb_hs <= '1'; ++ when x"1" => r_ora <= I_DATA; w_ora_hs <= '1'; ++ when x"2" => r_ddrb <= I_DATA; ++ when x"3" => r_ddra <= I_DATA; ++ ++ when x"B" => r_acr <= I_DATA; ++ when x"C" => r_pcr <= I_DATA; ++ when x"F" => r_ora <= I_DATA; ++ ++ when others => null; ++ end case; ++ end if; ++ ++ if (r_acr(7) = '1') and (t1_toggle = '1') then ++ r_orb(7) <= not r_orb(7); -- toggle ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ p_write_reg : process ++ begin ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ t1_w_reset_int <= false; ++ t1_load_counter <= false; ++ ++ t2_w_reset_int <= false; ++ t2_load_counter <= false; ++ ++ load_data <= x"00"; ++ sr_write_ena <= false; ++ ifr_write_ena <= false; ++ ier_write_ena <= false; ++ ++ if (cs = '1') and (I_RW_L = '0') then ++ load_data <= I_DATA; ++ case I_RS is ++ when x"4" => r_t1l_l <= I_DATA; ++ when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; ++ t1_load_counter <= true; ++ ++ when x"6" => r_t1l_l <= I_DATA; ++ when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; ++ ++ when x"8" => r_t2l_l <= I_DATA; ++ when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true; ++ t2_load_counter <= true; ++ ++ when x"A" => sr_write_ena <= true; ++ when x"D" => ifr_write_ena <= true; ++ when x"E" => ier_write_ena <= true; ++ ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end process; ++ ++ p_oe : process(cs, I_RW_L) ++ begin ++ O_DATA_OE_L <= '1'; ++ if (cs = '1') and (I_RW_L = '1') then ++ O_DATA_OE_L <= '0'; ++ end if; ++ end process; ++ ++ p_read : process ++ begin ++ wait until rising_edge(CLK); ++ ++ if ENA_4 = '1' then ++ t1_r_reset_int <= false; ++ t2_r_reset_int <= false; ++ sr_read_ena <= false; ++ r_irb_hs <= '0'; ++ r_ira_hs <= '0'; ++ ++ if (cs = '1') and (I_RW_L = '1') then ++ case I_RS is ++ --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1'; ++ -- fix from Mark McDougall, untested ++ when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1'; ++ when x"1" => O_DATA <= r_ira; r_ira_hs <= '1'; ++ when x"2" => O_DATA <= r_ddrb; ++ when x"3" => O_DATA <= r_ddra; ++ when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true; ++ when x"5" => O_DATA <= t1c(15 downto 8); ++ when x"6" => O_DATA <= r_t1l_l; ++ when x"7" => O_DATA <= r_t1l_h; ++ when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true; ++ when x"9" => O_DATA <= t2c(15 downto 8); ++ when x"A" => O_DATA <= r_sr; sr_read_ena <= true; ++ when x"B" => O_DATA <= r_acr; ++ when x"C" => O_DATA <= r_pcr; ++ when x"D" => O_DATA <= r_ifr; ++ when x"E" => O_DATA <= ('0' & r_ier); ++ when x"F" => O_DATA <= r_ira; ++ when others => null; ++ end case; ++ end if; ++ end if; ++ ++ end process; ++ -- ++ -- IO ++ -- ++ p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1) ++ begin ++ -- if the shift register is enabled, cb1 may be an output ++ -- in this case, we should listen to the CB1_OUT for the interrupt ++ if (sr_cb1_oe_l = '1') then ++ cb1_in_mux <= I_CB1; ++ else ++ cb1_in_mux <= sr_cb1_out; ++ end if; ++ end process; ++ ++ p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux) ++ begin ++ if (r_pcr(0) = '0') then -- ca1 control ++ -- negative edge ++ ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0'); ++ else ++ -- positive edge ++ ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1'); ++ end if; ++ ++ if (r_pcr(4) = '0') then -- cb1 control ++ -- negative edge ++ cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0'); ++ else ++ -- positive edge ++ cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1'); ++ end if; ++ end process; ++ ++ p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2) ++ begin ++ ca2_int <= false; ++ if (r_pcr(3) = '0') then -- ca2 input ++ if (r_pcr(2) = '0') then -- ca2 edge ++ -- negative edge ++ ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0'); ++ else ++ -- positive edge ++ ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1'); ++ end if; ++ end if; ++ ++ cb2_int <= false; ++ if (r_pcr(7) = '0') then -- cb2 input ++ if (r_pcr(6) = '0') then -- cb2 edge ++ -- negative edge ++ cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0'); ++ else ++ -- positive edge ++ cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1'); ++ end if; ++ end if; ++ end process; ++ ++ p_ca2_cb2 : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ O_CA2 <= '0'; ++ O_CA2_OE_L <= '1'; ++ O_CB2 <= '0'; ++ O_CB2_OE_L <= '1'; ++ ++ ca_hs_sr <= '0'; ++ ca_hs_pulse <= '0'; ++ cb_hs_sr <= '0'; ++ cb_hs_pulse <= '0'; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ -- ca ++ if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then ++ ca_hs_sr <= '1'; ++ elsif ca1_int then ++ ca_hs_sr <= '0'; ++ end if; ++ ++ if (phase = "00") then ++ ca_hs_pulse <= w_ora_hs or r_ira_hs; ++ end if; ++ ++ O_CA2_OE_L <= not r_pcr(3); -- ca2 output ++ case r_pcr(3 downto 1) is ++ when "000" => O_CA2 <= '0'; -- input ++ when "001" => O_CA2 <= '0'; -- input ++ when "010" => O_CA2 <= '0'; -- input ++ when "011" => O_CA2 <= '0'; -- input ++ when "100" => O_CA2 <= not (ca_hs_sr); -- handshake ++ when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse ++ when "110" => O_CA2 <= '0'; -- low ++ when "111" => O_CA2 <= '1'; -- high ++ when others => null; ++ end case; ++ ++ -- cb ++ if (phase = "00") and (w_orb_hs = '1') then ++ cb_hs_sr <= '1'; ++ elsif cb1_int then ++ cb_hs_sr <= '0'; ++ end if; ++ ++ if (phase = "00") then ++ cb_hs_pulse <= w_orb_hs; ++ end if; ++ ++ O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial ++ if (sr_drive_cb2 = '1') then -- serial output ++ O_CB2 <= sr_out; ++ else ++ case r_pcr(7 downto 5) is ++ when "000" => O_CB2 <= '0'; -- input ++ when "001" => O_CB2 <= '0'; -- input ++ when "010" => O_CB2 <= '0'; -- input ++ when "011" => O_CB2 <= '0'; -- input ++ when "100" => O_CB2 <= not (cb_hs_sr); -- handshake ++ when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse ++ when "110" => O_CB2 <= '0'; -- low ++ when "111" => O_CB2 <= '1'; -- high ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end if; ++ end process; ++ O_CB1 <= sr_cb1_out; ++ O_CB1_OE_L <= sr_cb1_oe_l; ++ ++ p_ca_cb_irq : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ ca1_irq <= '0'; ++ ca2_irq <= '0'; ++ cb1_irq <= '0'; ++ cb2_irq <= '0'; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ -- not pretty ++ if ca1_int then ++ ca1_irq <= '1'; ++ elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then ++ ca1_irq <= '0'; ++ end if; ++ ++ if ca2_int then ++ ca2_irq <= '1'; ++ else ++ if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or ++ (clear_irq(0) = '1') then ++ ca2_irq <= '0'; ++ end if; ++ end if; ++ ++ if cb1_int then ++ cb1_irq <= '1'; ++ elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then ++ cb1_irq <= '0'; ++ end if; ++ ++ if cb2_int then ++ cb2_irq <= '1'; ++ else ++ if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or ++ (clear_irq(3) = '1') then ++ cb2_irq <= '0'; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ p_input_reg : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ ca1_ip_reg <= '0'; ++ cb1_ip_reg <= '0'; ++ ++ ca2_ip_reg <= '0'; ++ cb2_ip_reg <= '0'; ++ ++ r_ira <= x"00"; ++ r_irb <= x"00"; ++ ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ -- we have a fast clock, so we can have input registers ++ ca1_ip_reg <= I_CA1; ++ cb1_ip_reg <= cb1_in_mux; ++ ++ ca2_ip_reg <= I_CA2; ++ cb2_ip_reg <= I_CB2; ++ ++ if (r_acr(0) = '0') then ++ r_ira <= I_PA; ++ else -- enable latching ++ if ca1_int then ++ r_ira <= I_PA; ++ end if; ++ end if; ++ ++ if (r_acr(1) = '0') then ++ r_irb <= I_PB; ++ else -- enable latching ++ if cb1_int then ++ r_irb <= I_PB; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ ++ p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb) ++ begin ++ -- data direction reg (ddr) 0 = input, 1 = output ++ O_PA <= r_ora; ++ O_PA_OE_L <= not r_ddra; ++ ++ if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well ++ O_PB_OE_L(7) <= '0'; -- an output if under t1 control ++ else ++ O_PB_OE_L(7) <= not (r_ddrb(7)); ++ end if; ++ ++ O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0); ++ O_PB(7 downto 0) <= r_orb(7 downto 0); ++ ++ end process; ++ -- ++ -- Timer 1 ++ -- ++ p_timer1_done : process(t1c,phase,r_acr) ++ variable done : boolean; ++ begin ++ done := (t1c = x"0000"); ++ t1c_done <= done and (phase = "11"); ++ --if (phase = "11") then ++ t1_reload_counter <= done and (r_acr(6) = '1'); ++ --end if; ++ end process; ++ ++ p_timer1 : process ++ begin ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ if t1_load_counter or (t1_reload_counter and phase = "11") then ++ t1c( 7 downto 0) <= r_t1l_l; ++ t1c(15 downto 8) <= r_t1l_h; ++ elsif (phase="11") then ++ t1c <= t1c - "1"; ++ end if; ++ ++ if t1_load_counter or t1_reload_counter then ++ t1c_active <= true; ++ elsif t1c_done then ++ t1c_active <= false; ++ end if; ++ if RESET_L = '0' then ++ t1c_active <= false; ++ end if; ++ ++ t1_toggle <= '0'; ++ if t1c_active and t1c_done then ++ t1_toggle <= '1'; ++ t1_irq <= '1'; ++ elsif RESET_L = '0' or t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then ++ t1_irq <= '0'; ++ end if; ++ end if; ++ end process; ++ -- ++ -- Timer2 ++ -- ++ p_timer2_pb6_input : process ++ begin ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ if (phase = "01") then -- leading edge p2_h ++ t2_pb6 <= I_PB(6); ++ t2_pb6_t1 <= t2_pb6; ++ end if; ++ end if; ++ end process; ++ ++ p_timer2_done : process(t2c,phase) ++ variable done : boolean; ++ begin ++ done := (t2c = x"0000"); ++ t2c_done <= done and (phase = "11"); ++ --if (phase = "11") then ++ t2_reload_counter <= done; ++ --end if; ++ end process; ++ ++ p_timer2 : process ++ variable ena : boolean; ++ begin ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ if (r_acr(5) = '0') then ++ ena := true; ++ else ++ ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge ++ end if; ++ ++ if t2_load_counter or (t2_reload_counter and phase = "11") then ++ -- not sure if t2c_reload should be here. Does timer2 just continue to ++ -- count down, or is it reloaded ? Reloaded makes more sense if using ++ -- it to generate a clock for the shift register. ++ t2c( 7 downto 0) <= r_t2l_l; ++ t2c(15 downto 8) <= r_t2l_h; ++ else ++ if (phase="11") and ena then -- or count mode ++ t2c <= t2c - "1"; ++ end if; ++ end if; ++ ++ t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11"); ++ ++ if t2_load_counter then ++ t2c_active <= true; ++ elsif t2c_done then ++ t2c_active <= false; ++ end if; ++ if RESET_L = '0' then ++ t2c_active <= false; ++ end if; ++ ++ if t2c_active and t2c_done then ++ t2_irq <= '1'; ++ elsif RESET_L = '0' or t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then ++ t2_irq <= '0'; ++ end if; ++ end if; ++ end process; ++ -- ++ -- Shift Register ++ -- ++ p_sr : process(RESET_L, CLK) ++ variable dir_out : std_logic; ++ variable ena : std_logic; ++ variable cb1_op : std_logic; ++ variable cb1_ip : std_logic; ++ variable use_t2 : std_logic; ++ variable free_run : std_logic; ++ variable sr_count_ena : boolean; ++ begin ++ if (RESET_L = '0') then ++ r_sr <= x"00"; ++ sr_drive_cb2 <= '0'; ++ sr_cb1_oe_l <= '1'; ++ sr_cb1_out <= '0'; ++ sr_strobe <= '1'; ++ sr_cnt <= "0000"; ++ sr_irq <= '0'; ++ sr_out <= '1'; ++ sr_off_delay <= '0'; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ -- decode mode ++ dir_out := r_acr(4); -- output on cb2 ++ cb1_op := '0'; ++ cb1_ip := '0'; ++ use_t2 := '0'; ++ free_run := '0'; ++ ++ case r_acr(4 downto 2) is ++ when "000" => ena := '0'; cb1_ip := '1'; ++ when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1'; ++ when "010" => ena := '1'; cb1_op := '1'; ++ when "011" => ena := '1'; cb1_ip := '1'; ++ when "100" => ena := '1'; use_t2 := '1'; free_run := '1'; ++ when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1'; ++ when "110" => ena := '1'; ++ when "111" => ena := '1'; cb1_ip := '1'; ++ when others => null; ++ end case; ++ ++ -- clock select ++ -- SR still runs even in disabled mode (on rising edge of CB1). It ++ -- just doesn't generate any interrupts. ++ -- Ref BBC micro advanced user guide p409 ++ if (cb1_ip = '1') then ++ sr_strobe <= I_CB1; ++ else ++ if (sr_cnt(3) = '0') and (free_run = '0') then ++ sr_strobe <= '1'; ++ else ++ if ((use_t2 = '1') and t2_sr_ena) or ++ ((use_t2 = '0') and (phase = "00")) then ++ sr_strobe <= not sr_strobe; ++ end if; ++ end if; ++ end if; ++ ++ -- latch on rising edge, shift on falling edge ++ if sr_write_ena then ++ r_sr <= load_data; ++ else ++ if (dir_out = '0') then ++ -- input ++ if (sr_cnt(3) = '1') or (cb1_ip = '1') then ++ if sr_strobe_rising then ++ r_sr <= r_sr(6 downto 0) & I_CB2; ++ end if; ++ end if; ++ sr_out <= '1'; ++ else ++ -- output ++ if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then ++ if sr_strobe_falling then ++ r_sr(7 downto 1) <= r_sr(6 downto 0); ++ r_sr(0) <= r_sr(7); ++ sr_out <= r_sr(7); ++ end if; ++ else ++ sr_out <= '1'; ++ end if; ++ end if; ++ end if; ++ ++ sr_count_ena := sr_strobe_rising; ++ ++ if sr_write_ena or sr_read_ena then ++ -- some documentation says sr bit in IFR must be set as well ? ++ sr_cnt <= "1000"; ++ elsif sr_count_ena and (sr_cnt(3) = '1') then ++ sr_cnt <= sr_cnt + "1"; ++ end if; ++ ++ if (phase = "00") then ++ sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out ++ end if; ++ ++ if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then ++ sr_irq <= '1'; ++ elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then ++ sr_irq <= '0'; ++ end if; ++ ++ -- assign ops ++ sr_drive_cb2 <= dir_out; ++ sr_cb1_oe_l <= not cb1_op; ++ sr_cb1_out <= sr_strobe; ++ end if; ++ end if; ++ end process; ++ ++ p_sr_strobe_rise_fall : process ++ begin ++ wait until rising_edge(CLK); ++ if (ENA_4 = '1') then ++ sr_strobe_t1 <= sr_strobe; ++ sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1'); ++ sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0'); ++ end if; ++ end process; ++ -- ++ -- Interrupts ++ -- ++ p_ier : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ r_ier <= "0000000"; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ if ier_write_ena then ++ if (load_data(7) = '1') then ++ -- set ++ r_ier <= r_ier or load_data(6 downto 0); ++ else ++ -- clear ++ r_ier <= r_ier and not load_data(6 downto 0); ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq, ++ cb1_irq, cb2_irq) ++ begin ++ r_ifr(7) <= final_irq; ++ r_ifr(6) <= t1_irq; ++ r_ifr(5) <= t2_irq; ++ r_ifr(4) <= cb1_irq; ++ r_ifr(3) <= cb2_irq; ++ r_ifr(2) <= sr_irq; ++ r_ifr(1) <= ca1_irq; ++ r_ifr(0) <= ca2_irq; ++ ++ O_IRQ_L <= not final_irq; ++ end process; ++ ++ p_irq : process(RESET_L, CLK) ++ begin ++ if (RESET_L = '0') then ++ final_irq <= '0'; ++ elsif rising_edge(CLK) then ++ if (ENA_4 = '1') then ++ if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then ++ final_irq <= '0'; -- no interrupts ++ else ++ final_irq <= '1'; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ p_clear_irq : process(ifr_write_ena, load_data) ++ begin ++ clear_irq <= x"00"; ++ if ifr_write_ena then ++ clear_irq <= load_data; ++ end if; ++ end process; ++ ++end architecture RTL; +diff --git a/m6522_tb.vhd b/m6522_tb.vhd +index 3e4262d..30307d2 100644 +--- a/m6522_tb.vhd ++++ b/m6522_tb.vhd +@@ -1,378 +1,378 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity m6522_tb is
+-end entity;
+-
+-architecture tb of m6522_tb is
+-
+-component M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable
+- CLK : in std_logic
+- );
+-end component;
+-
+-signal rs : std_logic_vector(3 downto 0) := "0000";
+-signal di : std_logic_vector(7 downto 0) := "00000000";
+-signal do : std_logic_vector(7 downto 0);
+-signal n_d_oe : std_logic;
+-signal r_nw : std_logic := '1';
+-signal cs1 : std_logic := '0';
+-signal n_cs2 : std_logic := '0';
+-signal n_irq : std_logic;
+-signal ca1_in : std_logic := '0';
+-signal ca2_in : std_logic := '0';
+-signal ca2_out : std_logic;
+-signal n_ca2_oe : std_logic;
+-signal pa_in : std_logic_vector(7 downto 0) := "00000000";
+-signal pa_out : std_logic_vector(7 downto 0);
+-signal n_pa_oe : std_logic_vector(7 downto 0);
+-signal cb1_in : std_logic := '0';
+-signal cb1_out : std_logic;
+-signal n_cb1_oe : std_logic;
+-signal cb2_in : std_logic := '0';
+-signal cb2_out : std_logic;
+-signal n_cb2_oe : std_logic;
+-signal pb_in : std_logic_vector(7 downto 0) := "00000000";
+-signal pb_out : std_logic_vector(7 downto 0);
+-signal n_pb_oe : std_logic_vector(7 downto 0);
+-
+-signal phase2 : std_logic := '0';
+-signal n_reset : std_logic := '0';
+-signal clken : std_logic := '0';
+-signal clock : std_logic := '0';
+-
+-begin
+-
+- uut: m6522 port map (
+- rs, di, do, n_d_oe,
+- r_nw, cs1, n_cs2, n_irq,
+- ca1_in, ca2_in, ca2_out, n_ca2_oe,
+- pa_in, pa_out, n_pa_oe,
+- cb1_in, cb1_out, n_cb1_oe,
+- cb2_in, cb2_out, n_cb2_oe,
+- pb_in, pb_out, n_pb_oe,
+- phase2, n_reset, clken, clock
+- );
+-
+- clock <= not clock after 125 ns; -- 4x 1 MHz
+- phase2 <= not phase2 after 500 ns;
+- clken <= '1'; -- all cycles enabled
+-
+- process
+- begin
+- wait for 1 us;
+- -- Release reset
+- n_reset <= '1';
+- end process;
+-
+- process
+-
+- procedure reg_write(
+- a : in std_logic_vector(3 downto 0);
+- d : in std_logic_vector(7 downto 0)) is
+- begin
+- wait until falling_edge(phase2);
+- rs <= a;
+- di <= d;
+- cs1 <= '1';
+- r_nw <= '0';
+- wait until falling_edge(phase2);
+- cs1 <= '0';
+- r_nw <= '1';
+- end procedure;
+-
+- procedure reg_read(
+- a : in std_logic_vector(3 downto 0)) is
+- begin
+- wait until falling_edge(phase2);
+- rs <= a;
+- cs1 <= '1';
+- r_nw <= '1';
+- wait until falling_edge(phase2);
+- cs1 <= '0';
+- end procedure;
+-
+- begin
+- wait for 2 us;
+-
+- -- Set port A and B to output
+- reg_write("0010","11111111");
+- reg_write("0011","11111111");
+-
+- -- Write to port B
+- reg_write("0000","10101010");
+- -- Write to port B
+- reg_write("0000","01010101");
+- -- Write to port A (no handshake)
+- reg_write("1111","10101010");
+- -- Write to port A (with handshake)
+- reg_write("0001","01010101");
+-
+- -- Set port A and B to input
+- reg_write("0010","00000000");
+- reg_write("0011","00000000");
+-
+- -- Apply input stimuli and read from ports
+- pa_in <= "10101010";
+- pb_in <= "01010101";
+- reg_read("0000");
+- reg_read("0001");
+-
+- -- Test CA1 interrupt
+- ca1_in <= '0';
+- reg_write("1100","00000001"); -- PCR - interrupt on rising edge
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10000010"); -- Enable CA1 interrupt
+- ca1_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+- ca1_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_write("1101","00000010"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1110","00000010"); -- Disable CA1 interrupt
+-
+- -- Test CB1 interrupt
+- cb1_in <= '0';
+- reg_write("1100","00010000"); -- PCR - interrupt on rising edge
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10010000"); -- Enable CB1 interrupt
+- cb1_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+- cb1_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_write("1101","00010000"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1110","00010000"); -- Disable CA1 interrupt
+-
+- -- Test CA2 interrupt modes
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10000001"); -- Enable CA2 interrupt
+- -- mode 2 (+ve edge, clear on read/write)
+- reg_write("1100","00000100"); -- PCR
+- ca2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 0 (-ve edge, clear on read/write)
+- reg_write("1100","00000000"); -- PCR
+- ca2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 3 (+ve edge, don't clear on read/write)
+- reg_write("1100","00000110");
+- ca2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should not clear interrupt
+- reg_write("1101","00000001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 1 (-ve edge, don't clear on read/write)
+- reg_write("1100","00000010");
+- ca2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should not clear interrupt
+- reg_write("1101","00000001"); -- Should clear interrupt
+- wait for 2 us;
+-
+- -- Test CA2 output modes
+- -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+- reg_write("1100","00001000");
+- -- mode 5 (set low for 1 cycle on read/write ORA)
+- reg_write("1100","00001010");
+- -- mode 6 (held low)
+- reg_write("1100","00001100");
+- -- mode 7 (held high)
+- reg_write("1100","00001110");
+-
+- -- Test CB2 interrupt modes
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10001000"); -- Enable CB2 interrupt
+- -- mode 2 (+ve edge, clear on read/write)
+- reg_write("1100","01000000"); -- PCR
+- cb2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 0 (-ve edge, clear on read/write)
+- reg_write("1100","00000000"); -- PCR
+- cb2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 3 (+ve edge, don't clear on read/write)
+- reg_write("1100","01100000");
+- cb2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should not clear interrupt
+- reg_write("1101","00001000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 1 (-ve edge, don't clear on read/write)
+- reg_write("1100","00100000");
+- cb2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should not clear interrupt
+- reg_write("1101","00001000"); -- Should clear interrupt
+- wait for 2 us;
+-
+- -- Test CB2 output modes
+- -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+- reg_write("1100","10000000");
+- -- mode 5 (set low for 1 cycle on read/write ORA)
+- reg_write("1100","10100000");
+- -- mode 6 (held low)
+- reg_write("1100","11000000");
+- -- mode 7 (held high)
+- reg_write("1100","11100000");
+-
+- -- Timer 1 timeout
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","11000000"); -- Enable timer 1 interrupt
+- -- Count to 16
+- reg_write("0100","00010000");
+- reg_write("0101","00000000");
+- wait for 50 us;
+- -- Count to 16
+- reg_write("0100","00010000");
+- reg_write("0101","00000000"); -- Should clear interrupt
+- wait for 50 us;
+- reg_read("0100"); -- Should clear interrupt
+-
+- -- Timer 2 timeout
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10100000"); -- Enable timer 2 interrupt
+- -- Count to 16
+- reg_write("1000","00010000");
+- reg_write("1001","00000000");
+- wait for 50 us;
+- -- Count to 16
+- reg_write("1000","00010000");
+- reg_write("1001","00000000"); -- Should clear interrupt
+- wait for 50 us;
+- reg_read("1000"); -- Should clear interrupt
+-
+- -- Timer 2 test similar to BBC usage (speech interrupt)
+- -- PB6 high
+- pb_in(6) <= '1';
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1011","00100000"); -- Timer 2 PB6 counter mode
+- reg_write("1000","00000001"); -- Start at 1
+- reg_write("1001","00000000");
+- reg_write("1110","10100000"); -- Enable timer 2 interrupt
+- wait for 5 us;
+- -- Generate falling edge
+- pb_in(6) <= '0';
+- wait for 5 us;
+- -- Clear interrupt
+- reg_write("1101","00100000");
+- -- Zero timer high byte
+- reg_write("1001","00000000");
+-
+- wait;
+- end process;
+-
+-end architecture;
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++ ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity m6522_tb is ++end entity; ++ ++architecture tb of m6522_tb is ++ ++component M6522 is ++ port ( ++ ++ I_RS : in std_logic_vector(3 downto 0); ++ I_DATA : in std_logic_vector(7 downto 0); ++ O_DATA : out std_logic_vector(7 downto 0); ++ O_DATA_OE_L : out std_logic; ++ ++ I_RW_L : in std_logic; ++ I_CS1 : in std_logic; ++ I_CS2_L : in std_logic; ++ ++ O_IRQ_L : out std_logic; -- note, not open drain ++ -- port a ++ I_CA1 : in std_logic; ++ I_CA2 : in std_logic; ++ O_CA2 : out std_logic; ++ O_CA2_OE_L : out std_logic; ++ ++ I_PA : in std_logic_vector(7 downto 0); ++ O_PA : out std_logic_vector(7 downto 0); ++ O_PA_OE_L : out std_logic_vector(7 downto 0); ++ ++ -- port b ++ I_CB1 : in std_logic; ++ O_CB1 : out std_logic; ++ O_CB1_OE_L : out std_logic; ++ ++ I_CB2 : in std_logic; ++ O_CB2 : out std_logic; ++ O_CB2_OE_L : out std_logic; ++ ++ I_PB : in std_logic_vector(7 downto 0); ++ O_PB : out std_logic_vector(7 downto 0); ++ O_PB_OE_L : out std_logic_vector(7 downto 0); ++ ++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__ ++ RESET_L : in std_logic; ++ ENA_4 : in std_logic; -- clk enable ++ CLK : in std_logic ++ ); ++end component; ++ ++signal rs : std_logic_vector(3 downto 0) := "0000"; ++signal di : std_logic_vector(7 downto 0) := "00000000"; ++signal do : std_logic_vector(7 downto 0); ++signal n_d_oe : std_logic; ++signal r_nw : std_logic := '1'; ++signal cs1 : std_logic := '0'; ++signal n_cs2 : std_logic := '0'; ++signal n_irq : std_logic; ++signal ca1_in : std_logic := '0'; ++signal ca2_in : std_logic := '0'; ++signal ca2_out : std_logic; ++signal n_ca2_oe : std_logic; ++signal pa_in : std_logic_vector(7 downto 0) := "00000000"; ++signal pa_out : std_logic_vector(7 downto 0); ++signal n_pa_oe : std_logic_vector(7 downto 0); ++signal cb1_in : std_logic := '0'; ++signal cb1_out : std_logic; ++signal n_cb1_oe : std_logic; ++signal cb2_in : std_logic := '0'; ++signal cb2_out : std_logic; ++signal n_cb2_oe : std_logic; ++signal pb_in : std_logic_vector(7 downto 0) := "00000000"; ++signal pb_out : std_logic_vector(7 downto 0); ++signal n_pb_oe : std_logic_vector(7 downto 0); ++ ++signal phase2 : std_logic := '0'; ++signal n_reset : std_logic := '0'; ++signal clken : std_logic := '0'; ++signal clock : std_logic := '0'; ++ ++begin ++ ++ uut: m6522 port map ( ++ rs, di, do, n_d_oe, ++ r_nw, cs1, n_cs2, n_irq, ++ ca1_in, ca2_in, ca2_out, n_ca2_oe, ++ pa_in, pa_out, n_pa_oe, ++ cb1_in, cb1_out, n_cb1_oe, ++ cb2_in, cb2_out, n_cb2_oe, ++ pb_in, pb_out, n_pb_oe, ++ phase2, n_reset, clken, clock ++ ); ++ ++ clock <= not clock after 125 ns; -- 4x 1 MHz ++ phase2 <= not phase2 after 500 ns; ++ clken <= '1'; -- all cycles enabled ++ ++ process ++ begin ++ wait for 1 us; ++ -- Release reset ++ n_reset <= '1'; ++ end process; ++ ++ process ++ ++ procedure reg_write( ++ a : in std_logic_vector(3 downto 0); ++ d : in std_logic_vector(7 downto 0)) is ++ begin ++ wait until falling_edge(phase2); ++ rs <= a; ++ di <= d; ++ cs1 <= '1'; ++ r_nw <= '0'; ++ wait until falling_edge(phase2); ++ cs1 <= '0'; ++ r_nw <= '1'; ++ end procedure; ++ ++ procedure reg_read( ++ a : in std_logic_vector(3 downto 0)) is ++ begin ++ wait until falling_edge(phase2); ++ rs <= a; ++ cs1 <= '1'; ++ r_nw <= '1'; ++ wait until falling_edge(phase2); ++ cs1 <= '0'; ++ end procedure; ++ ++ begin ++ wait for 2 us; ++ ++ -- Set port A and B to output ++ reg_write("0010","11111111"); ++ reg_write("0011","11111111"); ++ ++ -- Write to port B ++ reg_write("0000","10101010"); ++ -- Write to port B ++ reg_write("0000","01010101"); ++ -- Write to port A (no handshake) ++ reg_write("1111","10101010"); ++ -- Write to port A (with handshake) ++ reg_write("0001","01010101"); ++ ++ -- Set port A and B to input ++ reg_write("0010","00000000"); ++ reg_write("0011","00000000"); ++ ++ -- Apply input stimuli and read from ports ++ pa_in <= "10101010"; ++ pb_in <= "01010101"; ++ reg_read("0000"); ++ reg_read("0001"); ++ ++ -- Test CA1 interrupt ++ ca1_in <= '0'; ++ reg_write("1100","00000001"); -- PCR - interrupt on rising edge ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","10000010"); -- Enable CA1 interrupt ++ ca1_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0001"); -- Should clear interrupt ++ wait for 2 us; ++ reg_write("1100","00000000"); -- PCR - interrupt on falling edge ++ ca1_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_write("1101","00000010"); -- Should clear interrupt ++ wait for 2 us; ++ reg_write("1110","00000010"); -- Disable CA1 interrupt ++ ++ -- Test CB1 interrupt ++ cb1_in <= '0'; ++ reg_write("1100","00010000"); -- PCR - interrupt on rising edge ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","10010000"); -- Enable CB1 interrupt ++ cb1_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0000"); -- Should clear interrupt ++ wait for 2 us; ++ reg_write("1100","00000000"); -- PCR - interrupt on falling edge ++ cb1_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_write("1101","00010000"); -- Should clear interrupt ++ wait for 2 us; ++ reg_write("1110","00010000"); -- Disable CA1 interrupt ++ ++ -- Test CA2 interrupt modes ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","10000001"); -- Enable CA2 interrupt ++ -- mode 2 (+ve edge, clear on read/write) ++ reg_write("1100","00000100"); -- PCR ++ ca2_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("1111"); -- Should not clear interrupt ++ reg_read("0001"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 0 (-ve edge, clear on read/write) ++ reg_write("1100","00000000"); -- PCR ++ ca2_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("1111"); -- Should not clear interrupt ++ reg_read("0001"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 3 (+ve edge, don't clear on read/write) ++ reg_write("1100","00000110"); ++ ca2_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("1111"); -- Should not clear interrupt ++ reg_read("0001"); -- Should not clear interrupt ++ reg_write("1101","00000001"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 1 (-ve edge, don't clear on read/write) ++ reg_write("1100","00000010"); ++ ca2_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("1111"); -- Should not clear interrupt ++ reg_read("0001"); -- Should not clear interrupt ++ reg_write("1101","00000001"); -- Should clear interrupt ++ wait for 2 us; ++ ++ -- Test CA2 output modes ++ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge) ++ reg_write("1100","00001000"); ++ -- mode 5 (set low for 1 cycle on read/write ORA) ++ reg_write("1100","00001010"); ++ -- mode 6 (held low) ++ reg_write("1100","00001100"); ++ -- mode 7 (held high) ++ reg_write("1100","00001110"); ++ ++ -- Test CB2 interrupt modes ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","10001000"); -- Enable CB2 interrupt ++ -- mode 2 (+ve edge, clear on read/write) ++ reg_write("1100","01000000"); -- PCR ++ cb2_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0000"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 0 (-ve edge, clear on read/write) ++ reg_write("1100","00000000"); -- PCR ++ cb2_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0000"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 3 (+ve edge, don't clear on read/write) ++ reg_write("1100","01100000"); ++ cb2_in <= '1'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0000"); -- Should not clear interrupt ++ reg_write("1101","00001000"); -- Should clear interrupt ++ wait for 2 us; ++ -- mode 1 (-ve edge, don't clear on read/write) ++ reg_write("1100","00100000"); ++ cb2_in <= '0'; -- Trigger event ++ wait for 2 us; ++ reg_read("1101"); ++ reg_read("0000"); -- Should not clear interrupt ++ reg_write("1101","00001000"); -- Should clear interrupt ++ wait for 2 us; ++ ++ -- Test CB2 output modes ++ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge) ++ reg_write("1100","10000000"); ++ -- mode 5 (set low for 1 cycle on read/write ORA) ++ reg_write("1100","10100000"); ++ -- mode 6 (held low) ++ reg_write("1100","11000000"); ++ -- mode 7 (held high) ++ reg_write("1100","11100000"); ++ ++ -- Timer 1 timeout ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","11000000"); -- Enable timer 1 interrupt ++ -- Count to 16 ++ reg_write("0100","00010000"); ++ reg_write("0101","00000000"); ++ wait for 50 us; ++ -- Count to 16 ++ reg_write("0100","00010000"); ++ reg_write("0101","00000000"); -- Should clear interrupt ++ wait for 50 us; ++ reg_read("0100"); -- Should clear interrupt ++ ++ -- Timer 2 timeout ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1110","10100000"); -- Enable timer 2 interrupt ++ -- Count to 16 ++ reg_write("1000","00010000"); ++ reg_write("1001","00000000"); ++ wait for 50 us; ++ -- Count to 16 ++ reg_write("1000","00010000"); ++ reg_write("1001","00000000"); -- Should clear interrupt ++ wait for 50 us; ++ reg_read("1000"); -- Should clear interrupt ++ ++ -- Timer 2 test similar to BBC usage (speech interrupt) ++ -- PB6 high ++ pb_in(6) <= '1'; ++ reg_write("1101","01111111"); -- Clear interrupts ++ reg_write("1110","01111111"); -- Disable all interrupts ++ reg_write("1011","00100000"); -- Timer 2 PB6 counter mode ++ reg_write("1000","00000001"); -- Start at 1 ++ reg_write("1001","00000000"); ++ reg_write("1110","10100000"); -- Enable timer 2 interrupt ++ wait for 5 us; ++ -- Generate falling edge ++ pb_in(6) <= '0'; ++ wait for 5 us; ++ -- Clear interrupt ++ reg_write("1101","00100000"); ++ -- Zero timer high byte ++ reg_write("1001","00000000"); ++ ++ wait; ++ end process; ++ ++end architecture; +diff --git a/mc6845.vhd b/mc6845.vhd +index 31208ea..c102501 100644 +--- a/mc6845.vhd ++++ b/mc6845.vhd +@@ -1,481 +1,481 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- MC6845 CRTC
+---
+--- Synchronous implementation for FPGA
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity mc6845 is
+-port (
+- CLOCK : in std_logic;
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- R_nW : in std_logic;
+- RS : in std_logic;
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0);
+-
+- -- Display interface
+- VSYNC : out std_logic;
+- HSYNC : out std_logic;
+- DE : out std_logic;
+- CURSOR : out std_logic;
+- LPSTB : in std_logic;
+-
+- -- Memory interface
+- MA : out std_logic_vector(13 downto 0);
+- RA : out std_logic_vector(4 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of mc6845 is
+-
+--- Host-accessible registers
+-signal addr_reg : std_logic_vector(4 downto 0); -- Currently addressed register
+--- These are write-only
+-signal r00_h_total : unsigned(7 downto 0); -- Horizontal total, chars
+-signal r01_h_displayed : unsigned(7 downto 0); -- Horizontal active, chars
+-signal r02_h_sync_pos : unsigned(7 downto 0); -- Horizontal sync position, chars
+-signal r03_v_sync_width : unsigned(3 downto 0); -- Vertical sync width, scan lines (0=16 lines)
+-signal r03_h_sync_width : unsigned(3 downto 0); -- Horizontal sync width, chars (0=no sync)
+-signal r04_v_total : unsigned(6 downto 0); -- Vertical total, character rows
+-signal r05_v_total_adj : unsigned(4 downto 0); -- Vertical offset, scan lines
+-signal r06_v_displayed : unsigned(6 downto 0); -- Vertical active, character rows
+-signal r07_v_sync_pos : unsigned(6 downto 0); -- Vertical sync position, character rows
+-signal r08_interlace : std_logic_vector(1 downto 0);
+-signal r09_max_scan_line_addr : unsigned(4 downto 0);
+-signal r10_cursor_mode : std_logic_vector(1 downto 0);
+-signal r10_cursor_start : unsigned(4 downto 0); -- Cursor start, scan lines
+-signal r11_cursor_end : unsigned(4 downto 0); -- Cursor end, scan lines
+-signal r12_start_addr_h : unsigned(5 downto 0);
+-signal r13_start_addr_l : unsigned(7 downto 0);
+--- These are read/write
+-signal r14_cursor_h : unsigned(5 downto 0);
+-signal r15_cursor_l : unsigned(7 downto 0);
+--- These are read-only
+-signal r16_light_pen_h : unsigned(5 downto 0);
+-signal r17_light_pen_l : unsigned(7 downto 0);
+-
+-
+--- Timing generation
+--- Horizontal counter counts position on line
+-signal h_counter : unsigned(7 downto 0);
+--- HSYNC counter counts duration of sync pulse
+-signal h_sync_counter : unsigned(3 downto 0);
+--- Row counter counts current character row
+-signal row_counter : unsigned(6 downto 0);
+--- Line counter counts current line within each character row
+-signal line_counter : unsigned(4 downto 0);
+--- VSYNC counter counts duration of sync pulse
+-signal v_sync_counter : unsigned(3 downto 0);
+--- Field counter counts number of complete fields for cursor flash
+-signal field_counter : unsigned(5 downto 0);
+-
+--- Internal signals
+-signal h_sync_start : std_logic;
+-signal h_half_way : std_logic;
+-signal h_display : std_logic;
+-signal hs : std_logic;
+-signal v_display : std_logic;
+-signal vs : std_logic;
+-signal odd_field : std_logic;
+-signal ma_i : unsigned(13 downto 0);
+-signal ma_row_start : unsigned(13 downto 0); -- Start address of current character row
+-signal cursor_i : std_logic;
+-signal lpstb_i : std_logic;
+-
+-
+-begin
+- HSYNC <= hs; -- External HSYNC driven directly from internal signal
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- MC6845 CRTC ++-- ++-- Synchronous implementation for FPGA ++-- ++-- (C) 2011 Mike Stirling ++-- ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity mc6845 is ++port ( ++ CLOCK : in std_logic; ++ CLKEN : in std_logic; ++ nRESET : in std_logic; ++ ++ -- Bus interface ++ ENABLE : in std_logic; ++ R_nW : in std_logic; ++ RS : in std_logic; ++ DI : in std_logic_vector(7 downto 0); ++ DO : out std_logic_vector(7 downto 0); ++ ++ -- Display interface ++ VSYNC : out std_logic; ++ HSYNC : out std_logic; ++ DE : out std_logic; ++ CURSOR : out std_logic; ++ LPSTB : in std_logic; ++ ++ -- Memory interface ++ MA : out std_logic_vector(13 downto 0); ++ RA : out std_logic_vector(4 downto 0) ++ ); ++end entity; ++ ++architecture rtl of mc6845 is ++ ++-- Host-accessible registers ++signal addr_reg : std_logic_vector(4 downto 0); -- Currently addressed register ++-- These are write-only ++signal r00_h_total : unsigned(7 downto 0); -- Horizontal total, chars ++signal r01_h_displayed : unsigned(7 downto 0); -- Horizontal active, chars ++signal r02_h_sync_pos : unsigned(7 downto 0); -- Horizontal sync position, chars ++signal r03_v_sync_width : unsigned(3 downto 0); -- Vertical sync width, scan lines (0=16 lines) ++signal r03_h_sync_width : unsigned(3 downto 0); -- Horizontal sync width, chars (0=no sync) ++signal r04_v_total : unsigned(6 downto 0); -- Vertical total, character rows ++signal r05_v_total_adj : unsigned(4 downto 0); -- Vertical offset, scan lines ++signal r06_v_displayed : unsigned(6 downto 0); -- Vertical active, character rows ++signal r07_v_sync_pos : unsigned(6 downto 0); -- Vertical sync position, character rows ++signal r08_interlace : std_logic_vector(1 downto 0); ++signal r09_max_scan_line_addr : unsigned(4 downto 0); ++signal r10_cursor_mode : std_logic_vector(1 downto 0); ++signal r10_cursor_start : unsigned(4 downto 0); -- Cursor start, scan lines ++signal r11_cursor_end : unsigned(4 downto 0); -- Cursor end, scan lines ++signal r12_start_addr_h : unsigned(5 downto 0); ++signal r13_start_addr_l : unsigned(7 downto 0); ++-- These are read/write ++signal r14_cursor_h : unsigned(5 downto 0); ++signal r15_cursor_l : unsigned(7 downto 0); ++-- These are read-only ++signal r16_light_pen_h : unsigned(5 downto 0); ++signal r17_light_pen_l : unsigned(7 downto 0); ++ ++ ++-- Timing generation ++-- Horizontal counter counts position on line ++signal h_counter : unsigned(7 downto 0); ++-- HSYNC counter counts duration of sync pulse ++signal h_sync_counter : unsigned(3 downto 0); ++-- Row counter counts current character row ++signal row_counter : unsigned(6 downto 0); ++-- Line counter counts current line within each character row ++signal line_counter : unsigned(4 downto 0); ++-- VSYNC counter counts duration of sync pulse ++signal v_sync_counter : unsigned(3 downto 0); ++-- Field counter counts number of complete fields for cursor flash ++signal field_counter : unsigned(5 downto 0); ++ ++-- Internal signals ++signal h_sync_start : std_logic; ++signal h_half_way : std_logic; ++signal h_display : std_logic; ++signal hs : std_logic; ++signal v_display : std_logic; ++signal vs : std_logic; ++signal odd_field : std_logic; ++signal ma_i : unsigned(13 downto 0); ++signal ma_row_start : unsigned(13 downto 0); -- Start address of current character row ++signal cursor_i : std_logic; ++signal lpstb_i : std_logic; ++ ++ ++begin ++ HSYNC <= hs; -- External HSYNC driven directly from internal signal + VSYNC <= vs; -- External VSYNC driven directly from internal signal +- DE <= h_display and v_display;
+-
+- -- Cursor output generated combinatorially from the internal signal in
+- -- accordance with the currently selected cursor mode
+- CURSOR <= cursor_i when r10_cursor_mode = "00" else
+- '0' when r10_cursor_mode = "01" else
+- (cursor_i and field_counter(4)) when r10_cursor_mode = "10" else
+- (cursor_i and field_counter(5));
+-
+- -- Synchronous register access. Enabled on every clock.
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- -- Reset registers to defaults
+- addr_reg <= (others => '0');
+- r00_h_total <= (others => '0');
+- r01_h_displayed <= (others => '0');
+- r02_h_sync_pos <= (others => '0');
+- r03_v_sync_width <= (others => '0');
+- r03_h_sync_width <= (others => '0');
+- r04_v_total <= (others => '0');
+- r05_v_total_adj <= (others => '0');
+- r06_v_displayed <= (others => '0');
+- r07_v_sync_pos <= (others => '0');
+- r08_interlace <= (others => '0');
+- r09_max_scan_line_addr <= (others => '0');
+- r10_cursor_mode <= (others => '0');
+- r10_cursor_start <= (others => '0');
+- r11_cursor_end <= (others => '0');
+- r12_start_addr_h <= (others => '0');
+- r13_start_addr_l <= (others => '0');
+- r14_cursor_h <= (others => '0');
+- r15_cursor_l <= (others => '0');
+-
+- DO <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- if ENABLE = '1' then
+- if R_nW = '1' then
+- -- Read
+- case addr_reg is
+- when "01110" =>
+- DO <= "00" & std_logic_vector(r14_cursor_h);
+- when "01111" =>
+- DO <= std_logic_vector(r15_cursor_l);
+- when "10000" =>
+- DO <= "00" & std_logic_vector(r16_light_pen_h);
+- when "10001" =>
+- DO <= std_logic_vector(r17_light_pen_l);
+- when others =>
+- DO <= (others => '0');
+- end case;
+- else
+- -- Write
+- if RS = '0' then
+- addr_reg <= DI(4 downto 0);
+- else
+- case addr_reg is
+- when "00000" =>
+- r00_h_total <= unsigned(DI);
+- when "00001" =>
+- r01_h_displayed <= unsigned(DI);
+- when "00010" =>
+- r02_h_sync_pos <= unsigned(DI);
+- when "00011" =>
+- r03_v_sync_width <= unsigned(DI(7 downto 4));
+- r03_h_sync_width <= unsigned(DI(3 downto 0));
+- when "00100" =>
+- r04_v_total <= unsigned(DI(6 downto 0));
+- when "00101" =>
+- r05_v_total_adj <= unsigned(DI(4 downto 0));
+- when "00110" =>
+- r06_v_displayed <= unsigned(DI(6 downto 0));
+- when "00111" =>
+- r07_v_sync_pos <= unsigned(DI(6 downto 0));
+- when "01000" =>
+- r08_interlace <= DI(1 downto 0);
+- when "01001" =>
+- r09_max_scan_line_addr <= unsigned(DI(4 downto 0));
+- when "01010" =>
+- r10_cursor_mode <= DI(6 downto 5);
+- r10_cursor_start <= unsigned(DI(4 downto 0));
+- when "01011" =>
+- r11_cursor_end <= unsigned(DI(4 downto 0));
+- when "01100" =>
+- r12_start_addr_h <= unsigned(DI(5 downto 0));
+- when "01101" =>
+- r13_start_addr_l <= unsigned(DI(7 downto 0));
+- when "01110" =>
+- r14_cursor_h <= unsigned(DI(5 downto 0));
+- when "01111" =>
+- r15_cursor_l <= unsigned(DI(7 downto 0));
+- when others =>
+- null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process; -- registers
+-
+- -- Horizontal, vertical and address counters
+- process(CLOCK,nRESET)
+- variable ma_row_start : unsigned(13 downto 0);
+- variable max_scan_line : unsigned(4 downto 0);
+- begin
+- if nRESET = '0' then
+- -- H
+- h_counter <= (others => '0');
+-
+- -- V
+- line_counter <= (others => '0');
+- row_counter <= (others => '0');
+- odd_field <= '0';
+-
+- -- Fields (cursor flash)
+- field_counter <= (others => '0');
+-
+- -- Addressing
+- ma_row_start := (others => '0');
+- ma_i <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN='1' then
+- -- Horizontal counter increments on each clock, wrapping at
+- -- h_total
+- if h_counter = r00_h_total then
+- -- h_total reached
+- h_counter <= (others => '0');
+-
+- -- In interlace sync + video mode mask off the LSb of the
+- -- max scan line address
+- if r08_interlace = "11" then
+- max_scan_line := r09_max_scan_line_addr(4 downto 1) & "0";
+- else
+- max_scan_line := r09_max_scan_line_addr;
+- end if;
+-
+- -- Scan line counter increments, wrapping at max_scan_line_addr
+- if line_counter = max_scan_line then
+- -- Next character row
+- -- FIXME: No support for v_total_adj yet
+- line_counter <= (others => '0');
+- if row_counter = r04_v_total then
+- -- If in interlace mode we toggle to the opposite field.
+- -- Save on some logic by doing this here rather than at the
+- -- end of v_total_adj - it shouldn't make any difference to the
+- -- output
+- if r08_interlace(0) = '1' then
+- odd_field <= not odd_field;
+- else
+- odd_field <= '0';
+- end if;
+-
+- -- Address is loaded from start address register at the top of
+- -- each field and the row counter is reset
+- ma_row_start := r12_start_addr_h & r13_start_addr_l;
+- row_counter <= (others => '0');
+-
+- -- Increment field counter
+- field_counter <= field_counter + 1;
+- else
+- -- On all other character rows within the field the row start address is
+- -- increased by h_displayed and the row counter is incremented
+- ma_row_start := ma_row_start + r01_h_displayed;
+- row_counter <= row_counter + 1;
+- end if;
+- else
+- -- Next scan line. Count in twos in interlaced sync+video mode
+- if r08_interlace = "11" then
+- line_counter <= line_counter + 2;
+- line_counter(0) <= '0'; -- Force to even
+- else
+- line_counter <= line_counter + 1;
+- end if;
+- end if;
+-
+- -- Memory address preset to row start at the beginning of each
+- -- scan line
+- ma_i <= ma_row_start;
+- else
+- -- Increment horizontal counter
+- h_counter <= h_counter + 1;
+- -- Increment memory address
+- ma_i <= ma_i + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Signals to mark hsync and half way points for generating
+- -- vsync in even and odd fields
+- process(h_counter)
+- begin
+- h_sync_start <= '0';
+- h_half_way <= '0';
+-
+- if h_counter = r02_h_sync_pos then
+- h_sync_start <= '1';
+- end if;
+- if h_counter = "0" & r02_h_sync_pos(7 downto 1) then
+- h_half_way <= '1';
+- end if;
+- end process;
+-
+- -- Video timing and sync counters
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- -- H
+- h_display <= '0';
+- hs <= '0';
+- h_sync_counter <= (others => '0');
+-
+- -- V
+- v_display <= '0';
+- vs <= '0';
+- v_sync_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Horizontal active video
+- if h_counter = 0 then
+- -- Start of active video
+- h_display <= '1';
+- end if;
+- if h_counter = r01_h_displayed then
+- -- End of active video
+- h_display <= '0';
+- end if;
+-
+- -- Horizontal sync
+- if h_sync_start = '1' or hs = '1' then
+- -- In horizontal sync
+- hs <= '1';
+- h_sync_counter <= h_sync_counter + 1;
+- else
+- h_sync_counter <= (others => '0');
+- end if;
+- if h_sync_counter = r03_h_sync_width then
+- -- Terminate hsync after h_sync_width (0 means no hsync so this
+- -- can immediately override the setting above)
+- hs <= '0';
+- end if;
+-
+- -- Vertical active video
+- if row_counter = 0 then
+- -- Start of active video
+- v_display <= '1';
+- end if;
+- if row_counter = r06_v_displayed then
+- -- End of active video
+- v_display <= '0';
+- end if;
+-
+- -- Vertical sync occurs either at the same time as the horizontal sync (even fields)
+- -- or half a line later (odd fields)
+- if (odd_field = '0' and h_sync_start = '1') or (odd_field = '1' and h_half_way = '1') then
+- if (row_counter = r07_v_sync_pos and line_counter = 0) or vs = '1' then
+- -- In vertical sync
+- vs <= '1';
+- v_sync_counter <= v_sync_counter + 1;
+- else
+- v_sync_counter <= (others => '0');
+- end if;
+- if v_sync_counter = r03_v_sync_width and vs = '1' then
+- -- Terminate vsync after v_sync_width (0 means 16 lines so this is
+- -- masked by 'vs' to ensure a full turn of the counter in this case)
+- vs <= '0';
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Address generation
+- process(CLOCK,nRESET)
+- variable slv_line : std_logic_vector(4 downto 0);
+- begin
+- if nRESET = '0' then
+- RA <= (others => '0');
+- MA <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- slv_line := std_logic_vector(line_counter);
+-
+- -- Character row address is just the scan line counter delayed by
+- -- one clock to line up with the syncs.
+- if r08_interlace = "11" then
+- -- In interlace sync and video mode the LSb is determined by the
+- -- field number. The line counter counts up in 2s in this case.
+- RA <= slv_line(4 downto 1) & (slv_line(0) or odd_field);
+- else
+- RA <= slv_line;
+- end if;
+- -- Internal memory address delayed by one cycle as well
+- MA <= std_logic_vector(ma_i);
+- end if;
+- end process;
+-
+- -- Cursor control
+- process(CLOCK,nRESET)
+- variable cursor_line : std_logic;
+- begin
+- -- Internal cursor enable signal delayed by 1 clock to line up
+- -- with address outputs
+- if nRESET = '0' then
+- cursor_i <= '0';
+- cursor_line := '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if h_display = '1' and v_display = '1' and ma_i = r14_cursor_h & r15_cursor_l then
+- if line_counter = 0 then
+- -- Suppress wrap around if last line is > max scan line
+- cursor_line := '0';
+- end if;
+- if line_counter = r10_cursor_start then
+- -- First cursor scanline
+- cursor_line := '1';
+- end if;
+-
+- -- Cursor output is asserted within the current cursor character
+- -- on the selected lines only
+- cursor_i <= cursor_line;
+-
+- if line_counter = r11_cursor_end then
+- -- Last cursor scanline
+- cursor_line := '0';
+- end if;
+- else
+- -- Cursor is off in all character positions apart from the
+- -- selected one
+- cursor_i <= '0';
+- end if;
+- end if;
+- end process;
+-
+- -- Light pen capture
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- lpstb_i <= '0';
+- r16_light_pen_h <= (others => '0');
+- r17_light_pen_l <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Register light-pen strobe input
+- lpstb_i <= LPSTB;
+-
+- if LPSTB = '1' and lpstb_i = '0' then
+- -- Capture address on rising edge
+- r16_light_pen_h <= ma_i(13 downto 8);
+- r17_light_pen_l <= ma_i(7 downto 0);
+- end if;
+- end if;
+- end process;
+-end architecture;
+-
+-
++ DE <= h_display and v_display; ++ ++ -- Cursor output generated combinatorially from the internal signal in ++ -- accordance with the currently selected cursor mode ++ CURSOR <= cursor_i when r10_cursor_mode = "00" else ++ '0' when r10_cursor_mode = "01" else ++ (cursor_i and field_counter(4)) when r10_cursor_mode = "10" else ++ (cursor_i and field_counter(5)); ++ ++ -- Synchronous register access. Enabled on every clock. ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ -- Reset registers to defaults ++ addr_reg <= (others => '0'); ++ r00_h_total <= (others => '0'); ++ r01_h_displayed <= (others => '0'); ++ r02_h_sync_pos <= (others => '0'); ++ r03_v_sync_width <= (others => '0'); ++ r03_h_sync_width <= (others => '0'); ++ r04_v_total <= (others => '0'); ++ r05_v_total_adj <= (others => '0'); ++ r06_v_displayed <= (others => '0'); ++ r07_v_sync_pos <= (others => '0'); ++ r08_interlace <= (others => '0'); ++ r09_max_scan_line_addr <= (others => '0'); ++ r10_cursor_mode <= (others => '0'); ++ r10_cursor_start <= (others => '0'); ++ r11_cursor_end <= (others => '0'); ++ r12_start_addr_h <= (others => '0'); ++ r13_start_addr_l <= (others => '0'); ++ r14_cursor_h <= (others => '0'); ++ r15_cursor_l <= (others => '0'); ++ ++ DO <= (others => '0'); ++ elsif rising_edge(CLOCK) then ++ if ENABLE = '1' then ++ if R_nW = '1' then ++ -- Read ++ case addr_reg is ++ when "01110" => ++ DO <= "00" & std_logic_vector(r14_cursor_h); ++ when "01111" => ++ DO <= std_logic_vector(r15_cursor_l); ++ when "10000" => ++ DO <= "00" & std_logic_vector(r16_light_pen_h); ++ when "10001" => ++ DO <= std_logic_vector(r17_light_pen_l); ++ when others => ++ DO <= (others => '0'); ++ end case; ++ else ++ -- Write ++ if RS = '0' then ++ addr_reg <= DI(4 downto 0); ++ else ++ case addr_reg is ++ when "00000" => ++ r00_h_total <= unsigned(DI); ++ when "00001" => ++ r01_h_displayed <= unsigned(DI); ++ when "00010" => ++ r02_h_sync_pos <= unsigned(DI); ++ when "00011" => ++ r03_v_sync_width <= unsigned(DI(7 downto 4)); ++ r03_h_sync_width <= unsigned(DI(3 downto 0)); ++ when "00100" => ++ r04_v_total <= unsigned(DI(6 downto 0)); ++ when "00101" => ++ r05_v_total_adj <= unsigned(DI(4 downto 0)); ++ when "00110" => ++ r06_v_displayed <= unsigned(DI(6 downto 0)); ++ when "00111" => ++ r07_v_sync_pos <= unsigned(DI(6 downto 0)); ++ when "01000" => ++ r08_interlace <= DI(1 downto 0); ++ when "01001" => ++ r09_max_scan_line_addr <= unsigned(DI(4 downto 0)); ++ when "01010" => ++ r10_cursor_mode <= DI(6 downto 5); ++ r10_cursor_start <= unsigned(DI(4 downto 0)); ++ when "01011" => ++ r11_cursor_end <= unsigned(DI(4 downto 0)); ++ when "01100" => ++ r12_start_addr_h <= unsigned(DI(5 downto 0)); ++ when "01101" => ++ r13_start_addr_l <= unsigned(DI(7 downto 0)); ++ when "01110" => ++ r14_cursor_h <= unsigned(DI(5 downto 0)); ++ when "01111" => ++ r15_cursor_l <= unsigned(DI(7 downto 0)); ++ when others => ++ null; ++ end case; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; -- registers ++ ++ -- Horizontal, vertical and address counters ++ process(CLOCK,nRESET) ++ variable ma_row_start : unsigned(13 downto 0); ++ variable max_scan_line : unsigned(4 downto 0); ++ begin ++ if nRESET = '0' then ++ -- H ++ h_counter <= (others => '0'); ++ ++ -- V ++ line_counter <= (others => '0'); ++ row_counter <= (others => '0'); ++ odd_field <= '0'; ++ ++ -- Fields (cursor flash) ++ field_counter <= (others => '0'); ++ ++ -- Addressing ++ ma_row_start := (others => '0'); ++ ma_i <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN='1' then ++ -- Horizontal counter increments on each clock, wrapping at ++ -- h_total ++ if h_counter = r00_h_total then ++ -- h_total reached ++ h_counter <= (others => '0'); ++ ++ -- In interlace sync + video mode mask off the LSb of the ++ -- max scan line address ++ if r08_interlace = "11" then ++ max_scan_line := r09_max_scan_line_addr(4 downto 1) & "0"; ++ else ++ max_scan_line := r09_max_scan_line_addr; ++ end if; ++ ++ -- Scan line counter increments, wrapping at max_scan_line_addr ++ if line_counter = max_scan_line then ++ -- Next character row ++ -- FIXME: No support for v_total_adj yet ++ line_counter <= (others => '0'); ++ if row_counter = r04_v_total then ++ -- If in interlace mode we toggle to the opposite field. ++ -- Save on some logic by doing this here rather than at the ++ -- end of v_total_adj - it shouldn't make any difference to the ++ -- output ++ if r08_interlace(0) = '1' then ++ odd_field <= not odd_field; ++ else ++ odd_field <= '0'; ++ end if; ++ ++ -- Address is loaded from start address register at the top of ++ -- each field and the row counter is reset ++ ma_row_start := r12_start_addr_h & r13_start_addr_l; ++ row_counter <= (others => '0'); ++ ++ -- Increment field counter ++ field_counter <= field_counter + 1; ++ else ++ -- On all other character rows within the field the row start address is ++ -- increased by h_displayed and the row counter is incremented ++ ma_row_start := ma_row_start + r01_h_displayed; ++ row_counter <= row_counter + 1; ++ end if; ++ else ++ -- Next scan line. Count in twos in interlaced sync+video mode ++ if r08_interlace = "11" then ++ line_counter <= line_counter + 2; ++ line_counter(0) <= '0'; -- Force to even ++ else ++ line_counter <= line_counter + 1; ++ end if; ++ end if; ++ ++ -- Memory address preset to row start at the beginning of each ++ -- scan line ++ ma_i <= ma_row_start; ++ else ++ -- Increment horizontal counter ++ h_counter <= h_counter + 1; ++ -- Increment memory address ++ ma_i <= ma_i + 1; ++ end if; ++ end if; ++ end process; ++ ++ -- Signals to mark hsync and half way points for generating ++ -- vsync in even and odd fields ++ process(h_counter) ++ begin ++ h_sync_start <= '0'; ++ h_half_way <= '0'; ++ ++ if h_counter = r02_h_sync_pos then ++ h_sync_start <= '1'; ++ end if; ++ if h_counter = "0" & r02_h_sync_pos(7 downto 1) then ++ h_half_way <= '1'; ++ end if; ++ end process; ++ ++ -- Video timing and sync counters ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ -- H ++ h_display <= '0'; ++ hs <= '0'; ++ h_sync_counter <= (others => '0'); ++ ++ -- V ++ v_display <= '0'; ++ vs <= '0'; ++ v_sync_counter <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Horizontal active video ++ if h_counter = 0 then ++ -- Start of active video ++ h_display <= '1'; ++ end if; ++ if h_counter = r01_h_displayed then ++ -- End of active video ++ h_display <= '0'; ++ end if; ++ ++ -- Horizontal sync ++ if h_sync_start = '1' or hs = '1' then ++ -- In horizontal sync ++ hs <= '1'; ++ h_sync_counter <= h_sync_counter + 1; ++ else ++ h_sync_counter <= (others => '0'); ++ end if; ++ if h_sync_counter = r03_h_sync_width then ++ -- Terminate hsync after h_sync_width (0 means no hsync so this ++ -- can immediately override the setting above) ++ hs <= '0'; ++ end if; ++ ++ -- Vertical active video ++ if row_counter = 0 then ++ -- Start of active video ++ v_display <= '1'; ++ end if; ++ if row_counter = r06_v_displayed then ++ -- End of active video ++ v_display <= '0'; ++ end if; ++ ++ -- Vertical sync occurs either at the same time as the horizontal sync (even fields) ++ -- or half a line later (odd fields) ++ if (odd_field = '0' and h_sync_start = '1') or (odd_field = '1' and h_half_way = '1') then ++ if (row_counter = r07_v_sync_pos and line_counter = 0) or vs = '1' then ++ -- In vertical sync ++ vs <= '1'; ++ v_sync_counter <= v_sync_counter + 1; ++ else ++ v_sync_counter <= (others => '0'); ++ end if; ++ if v_sync_counter = r03_v_sync_width and vs = '1' then ++ -- Terminate vsync after v_sync_width (0 means 16 lines so this is ++ -- masked by 'vs' to ensure a full turn of the counter in this case) ++ vs <= '0'; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ -- Address generation ++ process(CLOCK,nRESET) ++ variable slv_line : std_logic_vector(4 downto 0); ++ begin ++ if nRESET = '0' then ++ RA <= (others => '0'); ++ MA <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ slv_line := std_logic_vector(line_counter); ++ ++ -- Character row address is just the scan line counter delayed by ++ -- one clock to line up with the syncs. ++ if r08_interlace = "11" then ++ -- In interlace sync and video mode the LSb is determined by the ++ -- field number. The line counter counts up in 2s in this case. ++ RA <= slv_line(4 downto 1) & (slv_line(0) or odd_field); ++ else ++ RA <= slv_line; ++ end if; ++ -- Internal memory address delayed by one cycle as well ++ MA <= std_logic_vector(ma_i); ++ end if; ++ end process; ++ ++ -- Cursor control ++ process(CLOCK,nRESET) ++ variable cursor_line : std_logic; ++ begin ++ -- Internal cursor enable signal delayed by 1 clock to line up ++ -- with address outputs ++ if nRESET = '0' then ++ cursor_i <= '0'; ++ cursor_line := '0'; ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ if h_display = '1' and v_display = '1' and ma_i = r14_cursor_h & r15_cursor_l then ++ if line_counter = 0 then ++ -- Suppress wrap around if last line is > max scan line ++ cursor_line := '0'; ++ end if; ++ if line_counter = r10_cursor_start then ++ -- First cursor scanline ++ cursor_line := '1'; ++ end if; ++ ++ -- Cursor output is asserted within the current cursor character ++ -- on the selected lines only ++ cursor_i <= cursor_line; ++ ++ if line_counter = r11_cursor_end then ++ -- Last cursor scanline ++ cursor_line := '0'; ++ end if; ++ else ++ -- Cursor is off in all character positions apart from the ++ -- selected one ++ cursor_i <= '0'; ++ end if; ++ end if; ++ end process; ++ ++ -- Light pen capture ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ lpstb_i <= '0'; ++ r16_light_pen_h <= (others => '0'); ++ r17_light_pen_l <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Register light-pen strobe input ++ lpstb_i <= LPSTB; ++ ++ if LPSTB = '1' and lpstb_i = '0' then ++ -- Capture address on rising edge ++ r16_light_pen_h <= ma_i(13 downto 8); ++ r17_light_pen_l <= ma_i(7 downto 0); ++ end if; ++ end if; ++ end process; ++end architecture; ++ ++ +diff --git a/pll32.ppf b/pll32.ppf +index 1ba6b2c..71486cf 100644 +--- a/pll32.ppf ++++ b/pll32.ppf +@@ -1,11 +1,11 @@ +-<?xml version="1.0" encoding="UTF-8" ?>
+-<!DOCTYPE pinplan>
+-<pinplan intended_family="Cyclone II" variation_name="pll32" megafunction_name="ALTPLL" specifies="all_ports">
+-<global>
+-<pin name="areset" direction="input" scope="external" />
+-<pin name="inclk0" direction="input" scope="external" source="clock" />
+-<pin name="c0" direction="output" scope="external" source="clock" />
+-<pin name="locked" direction="output" scope="external" />
+-
+-</global>
+-</pinplan>
++<?xml version="1.0" encoding="UTF-8" ?> ++<!DOCTYPE pinplan> ++<pinplan intended_family="Cyclone II" variation_name="pll32" megafunction_name="ALTPLL" specifies="all_ports"> ++<global> ++<pin name="areset" direction="input" scope="external" /> ++<pin name="inclk0" direction="input" scope="external" source="clock" /> ++<pin name="c0" direction="output" scope="external" source="clock" /> ++<pin name="locked" direction="output" scope="external" /> ++ ++</global> ++</pinplan> +diff --git a/pll32.qip b/pll32.qip +index f78bd93..e82abed 100644 +--- a/pll32.qip ++++ b/pll32.qip +@@ -1,4 +1,4 @@ +-set_global_assignment -name IP_TOOL_NAME "ALTPLL"
+-set_global_assignment -name IP_TOOL_VERSION "9.1"
+-set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll32.vhd"]
+-set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll32.ppf"]
++set_global_assignment -name IP_TOOL_NAME "ALTPLL" ++set_global_assignment -name IP_TOOL_VERSION "9.1" ++set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll32.vhd"] ++set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll32.ppf"] +diff --git a/pll32.vhd b/pll32.vhd +index 43df1aa..ab53700 100644 +--- a/pll32.vhd ++++ b/pll32.vhd +@@ -1,365 +1,365 @@ +--- megafunction wizard: %ALTPLL%
+--- GENERATION: STANDARD
+--- VERSION: WM1.0
+--- MODULE: altpll
+-
+--- ============================================================
+--- File Name: pll32.vhd
+--- Megafunction Name(s):
+--- altpll
+---
+--- Simulation Library Files(s):
+--- altera_mf
+--- ============================================================
+--- ************************************************************
+--- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+---
+--- 9.1 Build 222 10/21/2009 SJ Web Edition
+--- ************************************************************
+-
+-
+---Copyright (C) 1991-2009 Altera Corporation
+---Your use of Altera Corporation's design tools, logic functions
+---and other software and tools, and its AMPP partner logic
+---functions, and any output files from any of the foregoing
+---(including device programming or simulation files), and any
+---associated documentation or information are expressly subject
+---to the terms and conditions of the Altera Program License
+---Subscription Agreement, Altera MegaCore Function License
+---Agreement, or other applicable license agreement, including,
+---without limitation, that your use is for the sole purpose of
+---programming logic devices manufactured by Altera and sold by
+---Altera or its authorized distributors. Please refer to the
+---applicable agreement for further details.
+-
+-
+-LIBRARY ieee;
+-USE ieee.std_logic_1164.all;
+-
+-LIBRARY altera_mf;
+-USE altera_mf.all;
+-
+-ENTITY pll32 IS
+- PORT
+- (
+- areset : IN STD_LOGIC := '0';
+- inclk0 : IN STD_LOGIC := '0';
+- c0 : OUT STD_LOGIC ;
+- locked : OUT STD_LOGIC
+- );
+-END pll32;
+-
+-
+-ARCHITECTURE SYN OF pll32 IS
+-
+- SIGNAL sub_wire0 : STD_LOGIC_VECTOR (5 DOWNTO 0);
+- SIGNAL sub_wire1 : STD_LOGIC ;
+- SIGNAL sub_wire2 : STD_LOGIC ;
+- SIGNAL sub_wire3 : STD_LOGIC ;
+- SIGNAL sub_wire4 : STD_LOGIC_VECTOR (1 DOWNTO 0);
+- SIGNAL sub_wire5_bv : BIT_VECTOR (0 DOWNTO 0);
+- SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 DOWNTO 0);
+-
+-
+-
+- COMPONENT altpll
+- GENERIC (
+- clk0_divide_by : NATURAL;
+- clk0_duty_cycle : NATURAL;
+- clk0_multiply_by : NATURAL;
+- clk0_phase_shift : STRING;
+- compensate_clock : STRING;
+- gate_lock_signal : STRING;
+- inclk0_input_frequency : NATURAL;
+- intended_device_family : STRING;
+- invalid_lock_multiplier : NATURAL;
+- lpm_hint : STRING;
+- lpm_type : STRING;
+- operation_mode : STRING;
+- port_activeclock : STRING;
+- port_areset : STRING;
+- port_clkbad0 : STRING;
+- port_clkbad1 : STRING;
+- port_clkloss : STRING;
+- port_clkswitch : STRING;
+- port_configupdate : STRING;
+- port_fbin : STRING;
+- port_inclk0 : STRING;
+- port_inclk1 : STRING;
+- port_locked : STRING;
+- port_pfdena : STRING;
+- port_phasecounterselect : STRING;
+- port_phasedone : STRING;
+- port_phasestep : STRING;
+- port_phaseupdown : STRING;
+- port_pllena : STRING;
+- port_scanaclr : STRING;
+- port_scanclk : STRING;
+- port_scanclkena : STRING;
+- port_scandata : STRING;
+- port_scandataout : STRING;
+- port_scandone : STRING;
+- port_scanread : STRING;
+- port_scanwrite : STRING;
+- port_clk0 : STRING;
+- port_clk1 : STRING;
+- port_clk2 : STRING;
+- port_clk3 : STRING;
+- port_clk4 : STRING;
+- port_clk5 : STRING;
+- port_clkena0 : STRING;
+- port_clkena1 : STRING;
+- port_clkena2 : STRING;
+- port_clkena3 : STRING;
+- port_clkena4 : STRING;
+- port_clkena5 : STRING;
+- port_extclk0 : STRING;
+- port_extclk1 : STRING;
+- port_extclk2 : STRING;
+- port_extclk3 : STRING;
+- valid_lock_multiplier : NATURAL
+- );
+- PORT (
+- inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
+- locked : OUT STD_LOGIC ;
+- areset : IN STD_LOGIC ;
+- clk : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
+- );
+- END COMPONENT;
+-
+-BEGIN
+- sub_wire5_bv(0 DOWNTO 0) <= "0";
+- sub_wire5 <= To_stdlogicvector(sub_wire5_bv);
+- sub_wire1 <= sub_wire0(0);
+- c0 <= sub_wire1;
+- locked <= sub_wire2;
+- sub_wire3 <= inclk0;
+- sub_wire4 <= sub_wire5(0 DOWNTO 0) & sub_wire3;
+-
+- altpll_component : altpll
+- GENERIC MAP (
+- clk0_divide_by => 3,
+- clk0_duty_cycle => 50,
+- clk0_multiply_by => 4,
+- clk0_phase_shift => "0",
+- compensate_clock => "CLK0",
+- gate_lock_signal => "NO",
+- inclk0_input_frequency => 41666,
+- intended_device_family => "Cyclone II",
+- invalid_lock_multiplier => 5,
+- lpm_hint => "CBX_MODULE_PREFIX=pll32",
+- lpm_type => "altpll",
+- operation_mode => "NORMAL",
+- port_activeclock => "PORT_UNUSED",
+- port_areset => "PORT_USED",
+- port_clkbad0 => "PORT_UNUSED",
+- port_clkbad1 => "PORT_UNUSED",
+- port_clkloss => "PORT_UNUSED",
+- port_clkswitch => "PORT_UNUSED",
+- port_configupdate => "PORT_UNUSED",
+- port_fbin => "PORT_UNUSED",
+- port_inclk0 => "PORT_USED",
+- port_inclk1 => "PORT_UNUSED",
+- port_locked => "PORT_USED",
+- port_pfdena => "PORT_UNUSED",
+- port_phasecounterselect => "PORT_UNUSED",
+- port_phasedone => "PORT_UNUSED",
+- port_phasestep => "PORT_UNUSED",
+- port_phaseupdown => "PORT_UNUSED",
+- port_pllena => "PORT_UNUSED",
+- port_scanaclr => "PORT_UNUSED",
+- port_scanclk => "PORT_UNUSED",
+- port_scanclkena => "PORT_UNUSED",
+- port_scandata => "PORT_UNUSED",
+- port_scandataout => "PORT_UNUSED",
+- port_scandone => "PORT_UNUSED",
+- port_scanread => "PORT_UNUSED",
+- port_scanwrite => "PORT_UNUSED",
+- port_clk0 => "PORT_USED",
+- port_clk1 => "PORT_UNUSED",
+- port_clk2 => "PORT_UNUSED",
+- port_clk3 => "PORT_UNUSED",
+- port_clk4 => "PORT_UNUSED",
+- port_clk5 => "PORT_UNUSED",
+- port_clkena0 => "PORT_UNUSED",
+- port_clkena1 => "PORT_UNUSED",
+- port_clkena2 => "PORT_UNUSED",
+- port_clkena3 => "PORT_UNUSED",
+- port_clkena4 => "PORT_UNUSED",
+- port_clkena5 => "PORT_UNUSED",
+- port_extclk0 => "PORT_UNUSED",
+- port_extclk1 => "PORT_UNUSED",
+- port_extclk2 => "PORT_UNUSED",
+- port_extclk3 => "PORT_UNUSED",
+- valid_lock_multiplier => 1
+- )
+- PORT MAP (
+- inclk => sub_wire4,
+- areset => areset,
+- clk => sub_wire0,
+- locked => sub_wire2
+- );
+-
+-
+-
+-END SYN;
+-
+--- ============================================================
+--- CNX file retrieval info
+--- ============================================================
+--- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
+--- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
+--- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
+--- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"
+--- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
+--- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
+--- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
+--- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
+--- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
+--- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
+--- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "32.000000"
+--- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
+--- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
+--- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"
+--- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
+--- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
+--- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
+--- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "24.000"
+--- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
+--- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
+--- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
+--- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
+--- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "312.000"
+--- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
+--- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
+--- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
+--- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
+--- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
+--- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "32.00000000"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
+--- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
+--- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
+--- 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"
+--- Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
+--- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll32.mif"
+--- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
+--- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
+--- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
+--- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
+--- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
+--- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
+--- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
+--- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
+--- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
+--- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
+--- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+--- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
+--- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
+--- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
+--- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
+--- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+--- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3"
+--- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
+--- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4"
+--- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
+--- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
+--- Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO"
+--- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "41666"
+--- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: CONSTANT: INVALID_LOCK_MULTIPLIER NUMERIC "5"
+--- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
+--- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
+--- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: VALID_LOCK_MULTIPLIER NUMERIC "1"
+--- Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"
+--- Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]"
+--- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
+--- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
+--- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
+--- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
+--- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
+--- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
+--- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
+--- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
+--- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
+--- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.vhd TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.ppf TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.inc FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.cmp FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.bsf FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32_inst.vhd FALSE
+--- Retrieval info: LIB_FILE: altera_mf
+--- Retrieval info: CBX_MODULE_PREFIX: ON
++-- megafunction wizard: %ALTPLL% ++-- GENERATION: STANDARD ++-- VERSION: WM1.0 ++-- MODULE: altpll ++ ++-- ============================================================ ++-- File Name: pll32.vhd ++-- Megafunction Name(s): ++-- altpll ++-- ++-- Simulation Library Files(s): ++-- altera_mf ++-- ============================================================ ++-- ************************************************************ ++-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! ++-- ++-- 9.1 Build 222 10/21/2009 SJ Web Edition ++-- ************************************************************ ++ ++ ++--Copyright (C) 1991-2009 Altera Corporation ++--Your use of Altera Corporation's design tools, logic functions ++--and other software and tools, and its AMPP partner logic ++--functions, and any output files from any of the foregoing ++--(including device programming or simulation files), and any ++--associated documentation or information are expressly subject ++--to the terms and conditions of the Altera Program License ++--Subscription Agreement, Altera MegaCore Function License ++--Agreement, or other applicable license agreement, including, ++--without limitation, that your use is for the sole purpose of ++--programming logic devices manufactured by Altera and sold by ++--Altera or its authorized distributors. Please refer to the ++--applicable agreement for further details. ++ ++ ++LIBRARY ieee; ++USE ieee.std_logic_1164.all; ++ ++LIBRARY altera_mf; ++USE altera_mf.all; ++ ++ENTITY pll32 IS ++ PORT ++ ( ++ areset : IN STD_LOGIC := '0'; ++ inclk0 : IN STD_LOGIC := '0'; ++ c0 : OUT STD_LOGIC ; ++ locked : OUT STD_LOGIC ++ ); ++END pll32; ++ ++ ++ARCHITECTURE SYN OF pll32 IS ++ ++ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (5 DOWNTO 0); ++ SIGNAL sub_wire1 : STD_LOGIC ; ++ SIGNAL sub_wire2 : STD_LOGIC ; ++ SIGNAL sub_wire3 : STD_LOGIC ; ++ SIGNAL sub_wire4 : STD_LOGIC_VECTOR (1 DOWNTO 0); ++ SIGNAL sub_wire5_bv : BIT_VECTOR (0 DOWNTO 0); ++ SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 DOWNTO 0); ++ ++ ++ ++ COMPONENT altpll ++ GENERIC ( ++ clk0_divide_by : NATURAL; ++ clk0_duty_cycle : NATURAL; ++ clk0_multiply_by : NATURAL; ++ clk0_phase_shift : STRING; ++ compensate_clock : STRING; ++ gate_lock_signal : STRING; ++ inclk0_input_frequency : NATURAL; ++ intended_device_family : STRING; ++ invalid_lock_multiplier : NATURAL; ++ lpm_hint : STRING; ++ lpm_type : STRING; ++ operation_mode : STRING; ++ port_activeclock : STRING; ++ port_areset : STRING; ++ port_clkbad0 : STRING; ++ port_clkbad1 : STRING; ++ port_clkloss : STRING; ++ port_clkswitch : STRING; ++ port_configupdate : STRING; ++ port_fbin : STRING; ++ port_inclk0 : STRING; ++ port_inclk1 : STRING; ++ port_locked : STRING; ++ port_pfdena : STRING; ++ port_phasecounterselect : STRING; ++ port_phasedone : STRING; ++ port_phasestep : STRING; ++ port_phaseupdown : STRING; ++ port_pllena : STRING; ++ port_scanaclr : STRING; ++ port_scanclk : STRING; ++ port_scanclkena : STRING; ++ port_scandata : STRING; ++ port_scandataout : STRING; ++ port_scandone : STRING; ++ port_scanread : STRING; ++ port_scanwrite : STRING; ++ port_clk0 : STRING; ++ port_clk1 : STRING; ++ port_clk2 : STRING; ++ port_clk3 : STRING; ++ port_clk4 : STRING; ++ port_clk5 : STRING; ++ port_clkena0 : STRING; ++ port_clkena1 : STRING; ++ port_clkena2 : STRING; ++ port_clkena3 : STRING; ++ port_clkena4 : STRING; ++ port_clkena5 : STRING; ++ port_extclk0 : STRING; ++ port_extclk1 : STRING; ++ port_extclk2 : STRING; ++ port_extclk3 : STRING; ++ valid_lock_multiplier : NATURAL ++ ); ++ PORT ( ++ inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); ++ locked : OUT STD_LOGIC ; ++ areset : IN STD_LOGIC ; ++ clk : OUT STD_LOGIC_VECTOR (5 DOWNTO 0) ++ ); ++ END COMPONENT; ++ ++BEGIN ++ sub_wire5_bv(0 DOWNTO 0) <= "0"; ++ sub_wire5 <= To_stdlogicvector(sub_wire5_bv); ++ sub_wire1 <= sub_wire0(0); ++ c0 <= sub_wire1; ++ locked <= sub_wire2; ++ sub_wire3 <= inclk0; ++ sub_wire4 <= sub_wire5(0 DOWNTO 0) & sub_wire3; ++ ++ altpll_component : altpll ++ GENERIC MAP ( ++ clk0_divide_by => 3, ++ clk0_duty_cycle => 50, ++ clk0_multiply_by => 4, ++ clk0_phase_shift => "0", ++ compensate_clock => "CLK0", ++ gate_lock_signal => "NO", ++ inclk0_input_frequency => 41666, ++ intended_device_family => "Cyclone II", ++ invalid_lock_multiplier => 5, ++ lpm_hint => "CBX_MODULE_PREFIX=pll32", ++ lpm_type => "altpll", ++ operation_mode => "NORMAL", ++ port_activeclock => "PORT_UNUSED", ++ port_areset => "PORT_USED", ++ port_clkbad0 => "PORT_UNUSED", ++ port_clkbad1 => "PORT_UNUSED", ++ port_clkloss => "PORT_UNUSED", ++ port_clkswitch => "PORT_UNUSED", ++ port_configupdate => "PORT_UNUSED", ++ port_fbin => "PORT_UNUSED", ++ port_inclk0 => "PORT_USED", ++ port_inclk1 => "PORT_UNUSED", ++ port_locked => "PORT_USED", ++ port_pfdena => "PORT_UNUSED", ++ port_phasecounterselect => "PORT_UNUSED", ++ port_phasedone => "PORT_UNUSED", ++ port_phasestep => "PORT_UNUSED", ++ port_phaseupdown => "PORT_UNUSED", ++ port_pllena => "PORT_UNUSED", ++ port_scanaclr => "PORT_UNUSED", ++ port_scanclk => "PORT_UNUSED", ++ port_scanclkena => "PORT_UNUSED", ++ port_scandata => "PORT_UNUSED", ++ port_scandataout => "PORT_UNUSED", ++ port_scandone => "PORT_UNUSED", ++ port_scanread => "PORT_UNUSED", ++ port_scanwrite => "PORT_UNUSED", ++ port_clk0 => "PORT_USED", ++ port_clk1 => "PORT_UNUSED", ++ port_clk2 => "PORT_UNUSED", ++ port_clk3 => "PORT_UNUSED", ++ port_clk4 => "PORT_UNUSED", ++ port_clk5 => "PORT_UNUSED", ++ port_clkena0 => "PORT_UNUSED", ++ port_clkena1 => "PORT_UNUSED", ++ port_clkena2 => "PORT_UNUSED", ++ port_clkena3 => "PORT_UNUSED", ++ port_clkena4 => "PORT_UNUSED", ++ port_clkena5 => "PORT_UNUSED", ++ port_extclk0 => "PORT_UNUSED", ++ port_extclk1 => "PORT_UNUSED", ++ port_extclk2 => "PORT_UNUSED", ++ port_extclk3 => "PORT_UNUSED", ++ valid_lock_multiplier => 1 ++ ) ++ PORT MAP ( ++ inclk => sub_wire4, ++ areset => areset, ++ clk => sub_wire0, ++ locked => sub_wire2 ++ ); ++ ++ ++ ++END SYN; ++ ++-- ============================================================ ++-- CNX file retrieval info ++-- ============================================================ ++-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" ++-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" ++-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0" ++-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" ++-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" ++-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" ++-- Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0" ++-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" ++-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" ++-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" ++-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1" ++-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" ++-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" ++-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" ++-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" ++-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0" ++-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7" ++-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" ++-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" ++-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "32.000000" ++-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" ++-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" ++-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" ++-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1" ++-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" ++-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" ++-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" ++-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "24.000" ++-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" ++-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" ++-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" ++-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" ++-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" ++-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" ++-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" ++-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" ++-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" ++-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "312.000" ++-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" ++-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" ++-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" ++-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" ++-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1" ++-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" ++-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "32.00000000" ++-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" ++-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" ++-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0" ++-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" ++-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" ++-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" ++-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" ++-- 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" ++-- Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0" ++-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" ++-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" ++-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" ++-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" ++-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" ++-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" ++-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" ++-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll32.mif" ++-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" ++-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" ++-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" ++-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" ++-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" ++-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" ++-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" ++-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" ++-- Retrieval info: PRIVATE: SPREAD_USE STRING "0" ++-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" ++-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" ++-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" ++-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" ++-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" ++-- Retrieval info: PRIVATE: USE_CLK0 STRING "1" ++-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" ++-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" ++-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" ++-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all ++-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3" ++-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" ++-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4" ++-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" ++-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" ++-- Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO" ++-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "41666" ++-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" ++-- Retrieval info: CONSTANT: INVALID_LOCK_MULTIPLIER NUMERIC "5" ++-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" ++-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" ++-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" ++-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" ++-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" ++-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" ++-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" ++-- Retrieval info: CONSTANT: VALID_LOCK_MULTIPLIER NUMERIC "1" ++-- Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]" ++-- Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]" ++-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" ++-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" ++-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" ++-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" ++-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" ++-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 ++-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 ++-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 ++-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 ++-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.vhd TRUE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.ppf TRUE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.inc FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.cmp FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.bsf FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32_inst.vhd FALSE ++-- Retrieval info: LIB_FILE: altera_mf ++-- Retrieval info: CBX_MODULE_PREFIX: ON +diff --git a/ps2_intf.vhd b/ps2_intf.vhd +index dc8440f..015a7d0 100644 +--- a/ps2_intf.vhd ++++ b/ps2_intf.vhd +@@ -1,157 +1,157 @@ +--- ZX Spectrum for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+--- PS/2 interface (input only)
+--- Based loosely on ps2_ctrl.vhd (c) ALSE. http://www.alse-fr.com
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+--- This is input-only for the time being
+-entity ps2_intf is
+-generic (filter_length : positive := 8);
+-port(
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- PS/2 interface (could be bi-dir)
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- Byte-wide data interface - only valid for one clock
+- -- so must be latched externally if required
+- DATA : out std_logic_vector(7 downto 0);
+- VALID : out std_logic;
+- ERROR : out std_logic
+- );
+-end ps2_intf;
+-
+-architecture ps2_intf_arch of ps2_intf is
+-subtype filter_t is std_logic_vector(filter_length-1 downto 0);
+-signal clk_filter : filter_t;
+-
+-signal ps2_clk_in : std_logic;
+-signal ps2_dat_in : std_logic;
+--- Goes high when a clock falling edge is detected
+-signal clk_edge : std_logic;
+-signal bit_count : unsigned (3 downto 0);
+-signal shiftreg : std_logic_vector(8 downto 0);
+-signal parity : std_logic;
+-begin
+- -- Register input signals
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- ps2_clk_in <= '1';
+- ps2_dat_in <= '1';
+- clk_filter <= (others => '1');
+- clk_edge <= '0';
+- elsif rising_edge(CLK) then
+- -- Register inputs (and filter clock)
+- ps2_dat_in <= PS2_DATA;
+- clk_filter <= PS2_CLK & clk_filter(clk_filter'high downto 1);
+- clk_edge <= '0';
+-
+- if clk_filter = filter_t'(others => '1') then
+- -- Filtered clock is high
+- ps2_clk_in <= '1';
+- elsif clk_filter = filter_t'(others => '0') then
+- -- Filter clock is low, check for edge
+- if ps2_clk_in = '1' then
+- clk_edge <= '1';
+- end if;
+- ps2_clk_in <= '0';
+- end if;
+- end if;
+- end process;
+-
+- -- Shift in keyboard data
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- bit_count <= (others => '0');
+- shiftreg <= (others => '0');
+- parity <= '0';
+- DATA <= (others => '0');
+- VALID <= '0';
+- ERROR <= '0';
+- elsif rising_edge(CLK) then
+- -- Clear flags
+- VALID <= '0';
+- ERROR <= '0';
+-
+- if clk_edge = '1' then
+- -- We have a new bit from the keyboard for processing
+- if bit_count = 0 then
+- -- Idle state, check for start bit (0) only and don't
+- -- start counting bits until we get it
+-
+- parity <= '0';
+-
+- if ps2_dat_in = '0' then
+- -- This is a start bit
+- bit_count <= bit_count + 1;
+- end if;
+- else
+- -- Running. 8-bit data comes in LSb first followed by
+- -- a single stop bit (1)
+- if bit_count < 10 then
+- -- Shift in data and parity (9 bits)
+- bit_count <= bit_count + 1;
+- shiftreg <= ps2_dat_in & shiftreg(shiftreg'high downto 1);
+- parity <= parity xor ps2_dat_in; -- Calculate parity
+- elsif ps2_dat_in = '1' then
+- -- Valid stop bit received
+- bit_count <= (others => '0'); -- back to idle
+- if parity = '1' then
+- -- Parity correct, submit data to host
+- DATA <= shiftreg(7 downto 0);
+- VALID <= '1';
+- else
+- -- Error
+- ERROR <= '1';
+- end if;
+- else
+- -- Invalid stop bit
+- bit_count <= (others => '0'); -- back to idle
+- ERROR <= '1';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-end ps2_intf_arch;
++-- ZX Spectrum for Altera DE1 ++-- ++-- Copyright (c) 2009-2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++ ++-- PS/2 interface (input only) ++-- Based loosely on ps2_ctrl.vhd (c) ALSE. http://www.alse-fr.com ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++-- This is input-only for the time being ++entity ps2_intf is ++generic (filter_length : positive := 8); ++port( ++ CLK : in std_logic; ++ nRESET : in std_logic; ++ ++ -- PS/2 interface (could be bi-dir) ++ PS2_CLK : in std_logic; ++ PS2_DATA : in std_logic; ++ ++ -- Byte-wide data interface - only valid for one clock ++ -- so must be latched externally if required ++ DATA : out std_logic_vector(7 downto 0); ++ VALID : out std_logic; ++ ERROR : out std_logic ++ ); ++end ps2_intf; ++ ++architecture ps2_intf_arch of ps2_intf is ++subtype filter_t is std_logic_vector(filter_length-1 downto 0); ++signal clk_filter : filter_t; ++ ++signal ps2_clk_in : std_logic; ++signal ps2_dat_in : std_logic; ++-- Goes high when a clock falling edge is detected ++signal clk_edge : std_logic; ++signal bit_count : unsigned (3 downto 0); ++signal shiftreg : std_logic_vector(8 downto 0); ++signal parity : std_logic; ++begin ++ -- Register input signals ++ process(nRESET,CLK) ++ begin ++ if nRESET = '0' then ++ ps2_clk_in <= '1'; ++ ps2_dat_in <= '1'; ++ clk_filter <= (others => '1'); ++ clk_edge <= '0'; ++ elsif rising_edge(CLK) then ++ -- Register inputs (and filter clock) ++ ps2_dat_in <= PS2_DATA; ++ clk_filter <= PS2_CLK & clk_filter(clk_filter'high downto 1); ++ clk_edge <= '0'; ++ ++ if clk_filter = filter_t'(others => '1') then ++ -- Filtered clock is high ++ ps2_clk_in <= '1'; ++ elsif clk_filter = filter_t'(others => '0') then ++ -- Filter clock is low, check for edge ++ if ps2_clk_in = '1' then ++ clk_edge <= '1'; ++ end if; ++ ps2_clk_in <= '0'; ++ end if; ++ end if; ++ end process; ++ ++ -- Shift in keyboard data ++ process(nRESET,CLK) ++ begin ++ if nRESET = '0' then ++ bit_count <= (others => '0'); ++ shiftreg <= (others => '0'); ++ parity <= '0'; ++ DATA <= (others => '0'); ++ VALID <= '0'; ++ ERROR <= '0'; ++ elsif rising_edge(CLK) then ++ -- Clear flags ++ VALID <= '0'; ++ ERROR <= '0'; ++ ++ if clk_edge = '1' then ++ -- We have a new bit from the keyboard for processing ++ if bit_count = 0 then ++ -- Idle state, check for start bit (0) only and don't ++ -- start counting bits until we get it ++ ++ parity <= '0'; ++ ++ if ps2_dat_in = '0' then ++ -- This is a start bit ++ bit_count <= bit_count + 1; ++ end if; ++ else ++ -- Running. 8-bit data comes in LSb first followed by ++ -- a single stop bit (1) ++ if bit_count < 10 then ++ -- Shift in data and parity (9 bits) ++ bit_count <= bit_count + 1; ++ shiftreg <= ps2_dat_in & shiftreg(shiftreg'high downto 1); ++ parity <= parity xor ps2_dat_in; -- Calculate parity ++ elsif ps2_dat_in = '1' then ++ -- Valid stop bit received ++ bit_count <= (others => '0'); -- back to idle ++ if parity = '1' then ++ -- Parity correct, submit data to host ++ DATA <= shiftreg(7 downto 0); ++ VALID <= '1'; ++ else ++ -- Error ++ ERROR <= '1'; ++ end if; ++ else ++ -- Invalid stop bit ++ bit_count <= (others => '0'); -- back to idle ++ ERROR <= '1'; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++end ps2_intf_arch; +diff --git a/saa5050.vhd b/saa5050.vhd +index 57dd999..f198aa8 100644 +--- a/saa5050.vhd ++++ b/saa5050.vhd +@@ -1,391 +1,391 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- SAA5050 teletext generator
+---
+--- Synchronous implementation for FPGA. Certain TV-specific functions are
+--- not implemented. e.g.
+---
+--- No /SI pin - 'TEXT' mode is permanently enabled
+--- No remote control features (/DATA, DLIM)
+--- No large character support
+--- No support for box overlay (BLAN, PO, DE)
+--- No character rounding, although this may be added
+---
+--- FIXME: Hold graphics not supported - this needs to be added
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity saa5050 is
+-port (
+- CLOCK : in std_logic;
+- -- 6 MHz dot clock enable
+- CLKEN : in std_logic;
+- -- Async reset
+- nRESET : in std_logic;
+-
+- -- Character data input (in the bus clock domain)
+- DI_CLOCK : in std_logic;
+- DI_CLKEN : in std_logic;
+- DI : in std_logic_vector(6 downto 0);
+-
+- -- Timing inputs
+- -- General line reset (not used)
+- GLR : in std_logic; -- /HSYNC
+- -- Data entry window - high during VSYNC.
+- -- Resets ROM row counter and drives 'flash' signal
+- DEW : in std_logic; -- VSYNC
+- -- Character rounding select - high during even field
+- CRS : in std_logic; -- FIELD
+- -- Load output shift register enable - high during active video
+- LOSE : in std_logic; -- DE
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic;
+- Y : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of saa5050 is
+-
+-component saa5050_rom IS
+- PORT
+- (
+- address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- clock : IN STD_LOGIC ;
+- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+-end component;
+-
+--- Register inputs in the bus clock domain
+-signal di_r : std_logic_vector(6 downto 0);
+-signal dew_r : std_logic;
+-signal lose_r : std_logic;
+--- Data input registered in the pixel clock domain
+-signal code : std_logic_vector(6 downto 0);
+-signal line_addr : unsigned(3 downto 0);
+-signal rom_address : std_logic_vector(11 downto 0);
+-signal rom_data : std_logic_vector(7 downto 0);
+-
+--- Delayed display enable derived from LOSE by delaying for one character
+-signal disp_enable : std_logic;
+--- Latched timing signals for detection of falling edges
+-signal dew_latch : std_logic;
+-signal lose_latch : std_logic;
+-signal disp_enable_latch : std_logic;
+-
+--- Row and column addressing is handled externally. We just need to
+--- keep track of which of the 10 lines we are on within the character...
+-signal line_counter : unsigned(3 downto 0);
+--- ... and which of the 6 pixels we are on within each line
+-signal pixel_counter : unsigned(2 downto 0);
+--- We also need to count frames to implement the flash feature.
+--- The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it
+--- is probably a /64 counter, which gives us 0.78 Hz
+-signal flash_counter : unsigned(5 downto 0);
+--- Output shift register
+-signal shift_reg : std_logic_vector(5 downto 0);
+-
+--- Flash mask
+-signal flash : std_logic;
+-
+--- Current display state
+--- Foreground colour (B2, G1, R0)
+-signal fg : std_logic_vector(2 downto 0);
+--- Background colour (B2, G1, R0)
+-signal bg : std_logic_vector(2 downto 0);
+-signal conceal : std_logic;
+-signal gfx : std_logic;
+-signal gfx_sep : std_logic;
+-signal gfx_hold : std_logic;
+-signal is_flash : std_logic;
+-signal double_high : std_logic;
+--- Set in first row of double height
+-signal double_high1 : std_logic;
+--- Set in second row of double height
+-signal double_high2 : std_logic;
+-
+-begin
+- char_rom: saa5050_rom port map (
+- rom_address,
+- CLOCK,
+- rom_data
+- );
+-
+- -- Generate flash signal for 3:1 ratio
+- flash <= flash_counter(5) and flash_counter(4);
+-
+- -- Sync inputs
+- process(DI_CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- di_r <= (others => '0');
+- dew_r <= '0';
+- lose_r <= '0';
+- elsif rising_edge(DI_CLOCK) and DI_CLKEN = '1' then
+- di_r <= DI;
+- dew_r <= DEW;
+- lose_r <= LOSE;
+- end if;
+- end process;
+-
+- -- Register data into pixel clock domain
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- code <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- code <= di_r;
+- end if;
+- end process;
+-
+- -- Generate character rom address in pixel clock domain
+- -- This is done combinatorially since all the inputs are already
+- -- registered and the address is re-registered by the ROM
+- line_addr <= line_counter when double_high = '0' else
+- ("0" & line_counter(3 downto 1)) when double_high2 = '0' else
+- ("0" & line_counter(3 downto 1)) + 5;
+- rom_address <= (others => '0') when (double_high = '0' and double_high2 = '1') else
+- gfx & code & std_logic_vector(line_addr);
+-
+- -- Character row and pixel counters
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- dew_latch <= '0';
+- lose_latch <= '0';
+- disp_enable <= '0';
+- disp_enable_latch <= '0';
+- double_high1 <= '0';
+- double_high2 <= '0';
+- line_counter <= (others => '0');
+- pixel_counter <= (others => '0');
+- flash_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Register syncs for edge detection
+- dew_latch <= dew_r;
+- lose_latch <= lose_r;
+- disp_enable_latch <= disp_enable;
+-
+- -- When first entering double-height mode start on top row
+- if double_high = '1' and double_high1 = '0' and double_high2 = '0' then
+- double_high1 <= '1';
+- end if;
+-
+- -- Count pixels between 0 and 5
+- if pixel_counter = 5 then
+- -- Start of next character and delayed display enable
+- pixel_counter <= (others => '0');
+- disp_enable <= lose_latch;
+- else
+- pixel_counter <= pixel_counter + 1;
+- end if;
+-
+- -- Rising edge of LOSE is the start of the active line
+- if lose_r = '1' and lose_latch = '0' then
+- -- Reset pixel counter - small offset to make the output
+- -- line up with the cursor from the video ULA
+- pixel_counter <= "011";
+- end if;
+-
+- -- Count frames on end of VSYNC (falling edge of DEW)
+- if dew_r = '0' and dew_latch = '1' then
+- flash_counter <= flash_counter + 1;
+- end if;
+-
+- if dew_r = '1' then
+- -- Reset line counter and double height state during VSYNC
+- line_counter <= (others => '0');
+- double_high1 <= '0';
+- double_high2 <= '0';
+- else
+- -- Count lines on end of active video (falling edge of disp_enable)
+- if disp_enable = '0' and disp_enable_latch = '1' then
+- if line_counter = 9 then
+- line_counter <= (others => '0');
+-
+- -- Keep track of which row we are on for double-height
+- -- The double_high flag can be cleared before the end of a row, but if
+- -- double height characters are used anywhere on a row then the double_high1
+- -- flag will be set and remain set until the next row. This is used
+- -- to determine that the bottom half of the characters should be shown if
+- -- double_high is set once again on the row below.
+- double_high1 <= '0';
+- double_high2 <= double_high1;
+- else
+- line_counter <= line_counter + 1;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Shift register
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- shift_reg <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if disp_enable = '1' and pixel_counter = 0 then
+- -- Load the shift register with the ROM bit pattern
+- -- at the start of each character while disp_enable is asserted.
+- shift_reg <= rom_data(5 downto 0);
+-
+- -- If bit 7 of the ROM data is set then this is a graphics
+- -- character and separated/hold graphics modes apply.
+- -- We don't just assume this to be the case if gfx=1 because
+- -- these modes don't apply to caps even in graphics mode
+- if rom_data(7) = '1' then
+- -- Apply a mask for separated graphics mode
+- if gfx_sep = '1' then
+- shift_reg(5) <= '0';
+- shift_reg(2) <= '0';
+- if line_counter = 2 or line_counter = 6 or line_counter = 9 then
+- shift_reg <= (others => '0');
+- end if;
+- end if;
+- end if;
+- else
+- -- Pump the shift register
+- shift_reg <= shift_reg(4 downto 0) & "0";
+- end if;
+- end if;
+- end process;
+-
+- -- Control character handling
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- fg <= (others => '1');
+- bg <= (others => '0');
+- conceal <= '0';
+- gfx <= '0';
+- gfx_sep <= '0';
+- gfx_hold <= '0';
+- is_flash <= '0';
+- double_high <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if disp_enable = '0' then
+- -- Reset to start of line defaults
+- fg <= (others => '1');
+- bg <= (others => '0');
+- conceal <= '0';
+- gfx <= '0';
+- gfx_sep <= '0';
+- gfx_hold <= '0';
+- is_flash <= '0';
+- double_high <= '0';
+- elsif pixel_counter = 0 then
+- -- Latch new control codes at the start of each character
+- if code(6 downto 5) = "00" then
+- if code(3) = '0' then
+- -- Colour and graphics setting clears conceal mode
+- conceal <= '0';
+-
+- -- Select graphics or alpha mode
+- gfx <= code(4);
+-
+- -- 0 would be black but is not allowed so has no effect,
+- -- otherwise set the colour
+- if code(2 downto 0) /= "000" then
+- fg <= code(2 downto 0);
+- end if;
+- else
+- case code(4 downto 0) is
+- -- FLASH
+- when "01000" => is_flash <= '1';
+- -- STEADY
+- when "01001" => is_flash <= '0';
+- -- NORMAL HEIGHT
+- when "01100" => double_high <= '0';
+- -- DOUBLE HEIGHT
+- when "01101" => double_high <= '1';
+- -- CONCEAL
+- when "11000" => conceal <= '1';
+- -- CONTIGUOUS GFX
+- when "11001" => gfx_sep <= '0';
+- -- SEPARATED GFX
+- when "11010" => gfx_sep <= '1';
+- -- BLACK BACKGROUND
+- when "11100" => bg <= (others => '0');
+- -- NEW BACKGROUND
+- when "11101" => bg <= fg;
+- -- HOLD GFX
+- when "11110" => gfx_hold <= '1';
+- -- RELEASE GFX
+- when "11111" => gfx_hold <= '0';
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Output
+- process(CLOCK,nRESET)
+- variable pixel : std_logic;
+- begin
+- pixel := shift_reg(5) and not ((flash and is_flash) or conceal);
+-
+- if nRESET = '0' then
+- R <= '0';
+- G <= '0';
+- B <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Generate mono output
+- Y <= pixel;
+-
+- -- Generate colour output
+- if pixel = '1' then
+- R <= fg(0);
+- G <= fg(1);
+- B <= fg(2);
+- else
+- R <= bg(0);
+- G <= bg(1);
+- B <= bg(2);
+- end if;
+- end if;
+- end process;
+-end architecture;
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- SAA5050 teletext generator ++-- ++-- Synchronous implementation for FPGA. Certain TV-specific functions are ++-- not implemented. e.g. ++-- ++-- No /SI pin - 'TEXT' mode is permanently enabled ++-- No remote control features (/DATA, DLIM) ++-- No large character support ++-- No support for box overlay (BLAN, PO, DE) ++-- No character rounding, although this may be added ++-- ++-- FIXME: Hold graphics not supported - this needs to be added ++-- ++-- (C) 2011 Mike Stirling ++-- ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity saa5050 is ++port ( ++ CLOCK : in std_logic; ++ -- 6 MHz dot clock enable ++ CLKEN : in std_logic; ++ -- Async reset ++ nRESET : in std_logic; ++ ++ -- Character data input (in the bus clock domain) ++ DI_CLOCK : in std_logic; ++ DI_CLKEN : in std_logic; ++ DI : in std_logic_vector(6 downto 0); ++ ++ -- Timing inputs ++ -- General line reset (not used) ++ GLR : in std_logic; -- /HSYNC ++ -- Data entry window - high during VSYNC. ++ -- Resets ROM row counter and drives 'flash' signal ++ DEW : in std_logic; -- VSYNC ++ -- Character rounding select - high during even field ++ CRS : in std_logic; -- FIELD ++ -- Load output shift register enable - high during active video ++ LOSE : in std_logic; -- DE ++ ++ -- Video out ++ R : out std_logic; ++ G : out std_logic; ++ B : out std_logic; ++ Y : out std_logic ++ ); ++end entity; ++ ++architecture rtl of saa5050 is ++ ++component saa5050_rom IS ++ PORT ++ ( ++ address : IN STD_LOGIC_VECTOR (11 DOWNTO 0); ++ clock : IN STD_LOGIC ; ++ q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ++ ); ++end component; ++ ++-- Register inputs in the bus clock domain ++signal di_r : std_logic_vector(6 downto 0); ++signal dew_r : std_logic; ++signal lose_r : std_logic; ++-- Data input registered in the pixel clock domain ++signal code : std_logic_vector(6 downto 0); ++signal line_addr : unsigned(3 downto 0); ++signal rom_address : std_logic_vector(11 downto 0); ++signal rom_data : std_logic_vector(7 downto 0); ++ ++-- Delayed display enable derived from LOSE by delaying for one character ++signal disp_enable : std_logic; ++-- Latched timing signals for detection of falling edges ++signal dew_latch : std_logic; ++signal lose_latch : std_logic; ++signal disp_enable_latch : std_logic; ++ ++-- Row and column addressing is handled externally. We just need to ++-- keep track of which of the 10 lines we are on within the character... ++signal line_counter : unsigned(3 downto 0); ++-- ... and which of the 6 pixels we are on within each line ++signal pixel_counter : unsigned(2 downto 0); ++-- We also need to count frames to implement the flash feature. ++-- The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it ++-- is probably a /64 counter, which gives us 0.78 Hz ++signal flash_counter : unsigned(5 downto 0); ++-- Output shift register ++signal shift_reg : std_logic_vector(5 downto 0); ++ ++-- Flash mask ++signal flash : std_logic; ++ ++-- Current display state ++-- Foreground colour (B2, G1, R0) ++signal fg : std_logic_vector(2 downto 0); ++-- Background colour (B2, G1, R0) ++signal bg : std_logic_vector(2 downto 0); ++signal conceal : std_logic; ++signal gfx : std_logic; ++signal gfx_sep : std_logic; ++signal gfx_hold : std_logic; ++signal is_flash : std_logic; ++signal double_high : std_logic; ++-- Set in first row of double height ++signal double_high1 : std_logic; ++-- Set in second row of double height ++signal double_high2 : std_logic; ++ ++begin ++ char_rom: saa5050_rom port map ( ++ rom_address, ++ CLOCK, ++ rom_data ++ ); ++ ++ -- Generate flash signal for 3:1 ratio ++ flash <= flash_counter(5) and flash_counter(4); ++ ++ -- Sync inputs ++ process(DI_CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ di_r <= (others => '0'); ++ dew_r <= '0'; ++ lose_r <= '0'; ++ elsif rising_edge(DI_CLOCK) and DI_CLKEN = '1' then ++ di_r <= DI; ++ dew_r <= DEW; ++ lose_r <= LOSE; ++ end if; ++ end process; ++ ++ -- Register data into pixel clock domain ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ code <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ code <= di_r; ++ end if; ++ end process; ++ ++ -- Generate character rom address in pixel clock domain ++ -- This is done combinatorially since all the inputs are already ++ -- registered and the address is re-registered by the ROM ++ line_addr <= line_counter when double_high = '0' else ++ ("0" & line_counter(3 downto 1)) when double_high2 = '0' else ++ ("0" & line_counter(3 downto 1)) + 5; ++ rom_address <= (others => '0') when (double_high = '0' and double_high2 = '1') else ++ gfx & code & std_logic_vector(line_addr); ++ ++ -- Character row and pixel counters ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ dew_latch <= '0'; ++ lose_latch <= '0'; ++ disp_enable <= '0'; ++ disp_enable_latch <= '0'; ++ double_high1 <= '0'; ++ double_high2 <= '0'; ++ line_counter <= (others => '0'); ++ pixel_counter <= (others => '0'); ++ flash_counter <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Register syncs for edge detection ++ dew_latch <= dew_r; ++ lose_latch <= lose_r; ++ disp_enable_latch <= disp_enable; ++ ++ -- When first entering double-height mode start on top row ++ if double_high = '1' and double_high1 = '0' and double_high2 = '0' then ++ double_high1 <= '1'; ++ end if; ++ ++ -- Count pixels between 0 and 5 ++ if pixel_counter = 5 then ++ -- Start of next character and delayed display enable ++ pixel_counter <= (others => '0'); ++ disp_enable <= lose_latch; ++ else ++ pixel_counter <= pixel_counter + 1; ++ end if; ++ ++ -- Rising edge of LOSE is the start of the active line ++ if lose_r = '1' and lose_latch = '0' then ++ -- Reset pixel counter - small offset to make the output ++ -- line up with the cursor from the video ULA ++ pixel_counter <= "011"; ++ end if; ++ ++ -- Count frames on end of VSYNC (falling edge of DEW) ++ if dew_r = '0' and dew_latch = '1' then ++ flash_counter <= flash_counter + 1; ++ end if; ++ ++ if dew_r = '1' then ++ -- Reset line counter and double height state during VSYNC ++ line_counter <= (others => '0'); ++ double_high1 <= '0'; ++ double_high2 <= '0'; ++ else ++ -- Count lines on end of active video (falling edge of disp_enable) ++ if disp_enable = '0' and disp_enable_latch = '1' then ++ if line_counter = 9 then ++ line_counter <= (others => '0'); ++ ++ -- Keep track of which row we are on for double-height ++ -- The double_high flag can be cleared before the end of a row, but if ++ -- double height characters are used anywhere on a row then the double_high1 ++ -- flag will be set and remain set until the next row. This is used ++ -- to determine that the bottom half of the characters should be shown if ++ -- double_high is set once again on the row below. ++ double_high1 <= '0'; ++ double_high2 <= double_high1; ++ else ++ line_counter <= line_counter + 1; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ -- Shift register ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ shift_reg <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ if disp_enable = '1' and pixel_counter = 0 then ++ -- Load the shift register with the ROM bit pattern ++ -- at the start of each character while disp_enable is asserted. ++ shift_reg <= rom_data(5 downto 0); ++ ++ -- If bit 7 of the ROM data is set then this is a graphics ++ -- character and separated/hold graphics modes apply. ++ -- We don't just assume this to be the case if gfx=1 because ++ -- these modes don't apply to caps even in graphics mode ++ if rom_data(7) = '1' then ++ -- Apply a mask for separated graphics mode ++ if gfx_sep = '1' then ++ shift_reg(5) <= '0'; ++ shift_reg(2) <= '0'; ++ if line_counter = 2 or line_counter = 6 or line_counter = 9 then ++ shift_reg <= (others => '0'); ++ end if; ++ end if; ++ end if; ++ else ++ -- Pump the shift register ++ shift_reg <= shift_reg(4 downto 0) & "0"; ++ end if; ++ end if; ++ end process; ++ ++ -- Control character handling ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ fg <= (others => '1'); ++ bg <= (others => '0'); ++ conceal <= '0'; ++ gfx <= '0'; ++ gfx_sep <= '0'; ++ gfx_hold <= '0'; ++ is_flash <= '0'; ++ double_high <= '0'; ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ if disp_enable = '0' then ++ -- Reset to start of line defaults ++ fg <= (others => '1'); ++ bg <= (others => '0'); ++ conceal <= '0'; ++ gfx <= '0'; ++ gfx_sep <= '0'; ++ gfx_hold <= '0'; ++ is_flash <= '0'; ++ double_high <= '0'; ++ elsif pixel_counter = 0 then ++ -- Latch new control codes at the start of each character ++ if code(6 downto 5) = "00" then ++ if code(3) = '0' then ++ -- Colour and graphics setting clears conceal mode ++ conceal <= '0'; ++ ++ -- Select graphics or alpha mode ++ gfx <= code(4); ++ ++ -- 0 would be black but is not allowed so has no effect, ++ -- otherwise set the colour ++ if code(2 downto 0) /= "000" then ++ fg <= code(2 downto 0); ++ end if; ++ else ++ case code(4 downto 0) is ++ -- FLASH ++ when "01000" => is_flash <= '1'; ++ -- STEADY ++ when "01001" => is_flash <= '0'; ++ -- NORMAL HEIGHT ++ when "01100" => double_high <= '0'; ++ -- DOUBLE HEIGHT ++ when "01101" => double_high <= '1'; ++ -- CONCEAL ++ when "11000" => conceal <= '1'; ++ -- CONTIGUOUS GFX ++ when "11001" => gfx_sep <= '0'; ++ -- SEPARATED GFX ++ when "11010" => gfx_sep <= '1'; ++ -- BLACK BACKGROUND ++ when "11100" => bg <= (others => '0'); ++ -- NEW BACKGROUND ++ when "11101" => bg <= fg; ++ -- HOLD GFX ++ when "11110" => gfx_hold <= '1'; ++ -- RELEASE GFX ++ when "11111" => gfx_hold <= '0'; ++ ++ when others => null; ++ end case; ++ end if; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ -- Output ++ process(CLOCK,nRESET) ++ variable pixel : std_logic; ++ begin ++ pixel := shift_reg(5) and not ((flash and is_flash) or conceal); ++ ++ if nRESET = '0' then ++ R <= '0'; ++ G <= '0'; ++ B <= '0'; ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Generate mono output ++ Y <= pixel; ++ ++ -- Generate colour output ++ if pixel = '1' then ++ R <= fg(0); ++ G <= fg(1); ++ B <= fg(2); ++ else ++ R <= bg(0); ++ G <= bg(1); ++ B <= bg(2); ++ end if; ++ end if; ++ end process; ++end architecture; +diff --git a/saa5050_rom.qip b/saa5050_rom.qip +index e9513f7..be776f1 100644 +--- a/saa5050_rom.qip ++++ b/saa5050_rom.qip +@@ -1,3 +1,3 @@ +-set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT"
+-set_global_assignment -name IP_TOOL_VERSION "9.1"
+-set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "saa5050_rom.vhd"]
++set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" ++set_global_assignment -name IP_TOOL_VERSION "9.1" ++set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "saa5050_rom.vhd"] +diff --git a/saa5050_rom.vhd b/saa5050_rom.vhd +index 7541c0b..e1c702d 100644 +--- a/saa5050_rom.vhd ++++ b/saa5050_rom.vhd +@@ -1,168 +1,168 @@ +--- megafunction wizard: %ROM: 1-PORT%
+--- GENERATION: STANDARD
+--- VERSION: WM1.0
+--- MODULE: altsyncram
+-
+--- ============================================================
+--- File Name: saa5050_rom.vhd
+--- Megafunction Name(s):
+--- altsyncram
+---
+--- Simulation Library Files(s):
+--- altera_mf
+--- ============================================================
+--- ************************************************************
+--- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+---
+--- 9.1 Build 222 10/21/2009 SJ Web Edition
+--- ************************************************************
+-
+-
+---Copyright (C) 1991-2009 Altera Corporation
+---Your use of Altera Corporation's design tools, logic functions
+---and other software and tools, and its AMPP partner logic
+---functions, and any output files from any of the foregoing
+---(including device programming or simulation files), and any
+---associated documentation or information are expressly subject
+---to the terms and conditions of the Altera Program License
+---Subscription Agreement, Altera MegaCore Function License
+---Agreement, or other applicable license agreement, including,
+---without limitation, that your use is for the sole purpose of
+---programming logic devices manufactured by Altera and sold by
+---Altera or its authorized distributors. Please refer to the
+---applicable agreement for further details.
+-
+-
+-LIBRARY ieee;
+-USE ieee.std_logic_1164.all;
+-
+-LIBRARY altera_mf;
+-USE altera_mf.all;
+-
+-ENTITY saa5050_rom IS
+- PORT
+- (
+- address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- clock : IN STD_LOGIC ;
+- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+-END saa5050_rom;
+-
+-
+-ARCHITECTURE SYN OF saa5050_rom IS
+-
+- SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
+-
+-
+-
+- COMPONENT altsyncram
+- GENERIC (
+- clock_enable_input_a : STRING;
+- clock_enable_output_a : STRING;
+- init_file : STRING;
+- intended_device_family : STRING;
+- lpm_hint : STRING;
+- lpm_type : STRING;
+- numwords_a : NATURAL;
+- operation_mode : STRING;
+- outdata_aclr_a : STRING;
+- outdata_reg_a : STRING;
+- widthad_a : NATURAL;
+- width_a : NATURAL;
+- width_byteena_a : NATURAL
+- );
+- PORT (
+- clock0 : IN STD_LOGIC ;
+- address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+- END COMPONENT;
+-
+-BEGIN
+- q <= sub_wire0(7 DOWNTO 0);
+-
+- altsyncram_component : altsyncram
+- GENERIC MAP (
+- clock_enable_input_a => "BYPASS",
+- clock_enable_output_a => "BYPASS",
+- init_file => "./roms/saa5050/saa5050.hex",
+- intended_device_family => "Cyclone II",
+- lpm_hint => "ENABLE_RUNTIME_MOD=NO",
+- lpm_type => "altsyncram",
+- numwords_a => 4096,
+- operation_mode => "ROM",
+- outdata_aclr_a => "NONE",
+- outdata_reg_a => "UNREGISTERED",
+- widthad_a => 12,
+- width_a => 8,
+- width_byteena_a => 1
+- )
+- PORT MAP (
+- clock0 => clock,
+- address_a => address,
+- q_a => sub_wire0
+- );
+-
+-
+-
+-END SYN;
+-
+--- ============================================================
+--- CNX file retrieval info
+--- ============================================================
+--- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
+--- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
+--- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
+--- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
+--- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
+--- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
+--- Retrieval info: PRIVATE: Clken NUMERIC "0"
+--- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
+--- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
+--- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
+--- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
+--- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
+--- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
+--- Retrieval info: PRIVATE: MIFfilename STRING "./roms/saa5050/saa5050.hex"
+--- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096"
+--- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
+--- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
+--- Retrieval info: PRIVATE: RegOutput NUMERIC "0"
+--- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+--- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
+--- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
+--- Retrieval info: PRIVATE: WidthAddr NUMERIC "12"
+--- Retrieval info: PRIVATE: WidthData NUMERIC "8"
+--- Retrieval info: PRIVATE: rden NUMERIC "0"
+--- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
+--- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
+--- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/saa5050/saa5050.hex"
+--- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
+--- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
+--- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
+--- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
+--- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
+--- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
+--- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
+--- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
+--- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
+--- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[11..0]
+--- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+--- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
+--- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0
+--- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
+--- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
+--- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.vhd TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.inc FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.cmp FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.bsf FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_inst.vhd FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_waveforms.html FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_wave*.jpg FALSE
+--- Retrieval info: LIB_FILE: altera_mf
++-- megafunction wizard: %ROM: 1-PORT% ++-- GENERATION: STANDARD ++-- VERSION: WM1.0 ++-- MODULE: altsyncram ++ ++-- ============================================================ ++-- File Name: saa5050_rom.vhd ++-- Megafunction Name(s): ++-- altsyncram ++-- ++-- Simulation Library Files(s): ++-- altera_mf ++-- ============================================================ ++-- ************************************************************ ++-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! ++-- ++-- 9.1 Build 222 10/21/2009 SJ Web Edition ++-- ************************************************************ ++ ++ ++--Copyright (C) 1991-2009 Altera Corporation ++--Your use of Altera Corporation's design tools, logic functions ++--and other software and tools, and its AMPP partner logic ++--functions, and any output files from any of the foregoing ++--(including device programming or simulation files), and any ++--associated documentation or information are expressly subject ++--to the terms and conditions of the Altera Program License ++--Subscription Agreement, Altera MegaCore Function License ++--Agreement, or other applicable license agreement, including, ++--without limitation, that your use is for the sole purpose of ++--programming logic devices manufactured by Altera and sold by ++--Altera or its authorized distributors. Please refer to the ++--applicable agreement for further details. ++ ++ ++LIBRARY ieee; ++USE ieee.std_logic_1164.all; ++ ++LIBRARY altera_mf; ++USE altera_mf.all; ++ ++ENTITY saa5050_rom IS ++ PORT ++ ( ++ address : IN STD_LOGIC_VECTOR (11 DOWNTO 0); ++ clock : IN STD_LOGIC ; ++ q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ++ ); ++END saa5050_rom; ++ ++ ++ARCHITECTURE SYN OF saa5050_rom IS ++ ++ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0); ++ ++ ++ ++ COMPONENT altsyncram ++ GENERIC ( ++ clock_enable_input_a : STRING; ++ clock_enable_output_a : STRING; ++ init_file : STRING; ++ intended_device_family : STRING; ++ lpm_hint : STRING; ++ lpm_type : STRING; ++ numwords_a : NATURAL; ++ operation_mode : STRING; ++ outdata_aclr_a : STRING; ++ outdata_reg_a : STRING; ++ widthad_a : NATURAL; ++ width_a : NATURAL; ++ width_byteena_a : NATURAL ++ ); ++ PORT ( ++ clock0 : IN STD_LOGIC ; ++ address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0); ++ q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) ++ ); ++ END COMPONENT; ++ ++BEGIN ++ q <= sub_wire0(7 DOWNTO 0); ++ ++ altsyncram_component : altsyncram ++ GENERIC MAP ( ++ clock_enable_input_a => "BYPASS", ++ clock_enable_output_a => "BYPASS", ++ init_file => "./roms/saa5050/saa5050.hex", ++ intended_device_family => "Cyclone II", ++ lpm_hint => "ENABLE_RUNTIME_MOD=NO", ++ lpm_type => "altsyncram", ++ numwords_a => 4096, ++ operation_mode => "ROM", ++ outdata_aclr_a => "NONE", ++ outdata_reg_a => "UNREGISTERED", ++ widthad_a => 12, ++ width_a => 8, ++ width_byteena_a => 1 ++ ) ++ PORT MAP ( ++ clock0 => clock, ++ address_a => address, ++ q_a => sub_wire0 ++ ); ++ ++ ++ ++END SYN; ++ ++-- ============================================================ ++-- CNX file retrieval info ++-- ============================================================ ++-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" ++-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" ++-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" ++-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" ++-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" ++-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" ++-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0" ++-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" ++-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" ++-- Retrieval info: PRIVATE: Clken NUMERIC "0" ++-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" ++-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" ++-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" ++-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" ++-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" ++-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" ++-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" ++-- Retrieval info: PRIVATE: MIFfilename STRING "./roms/saa5050/saa5050.hex" ++-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" ++-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" ++-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" ++-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" ++-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" ++-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" ++-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" ++-- Retrieval info: PRIVATE: WidthAddr NUMERIC "12" ++-- Retrieval info: PRIVATE: WidthData NUMERIC "8" ++-- Retrieval info: PRIVATE: rden NUMERIC "0" ++-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" ++-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" ++-- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/saa5050/saa5050.hex" ++-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" ++-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" ++-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" ++-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" ++-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" ++-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" ++-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" ++-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" ++-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" ++-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" ++-- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[11..0] ++-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock ++-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0] ++-- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0 ++-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 ++-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 ++-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.vhd TRUE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.inc FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.cmp FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.bsf FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_inst.vhd FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_waveforms.html FALSE ++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_wave*.jpg FALSE ++-- Retrieval info: LIB_FILE: altera_mf +diff --git a/seg7.vhd b/seg7.vhd +index a61e679..566b1f6 100644 +--- a/seg7.vhd ++++ b/seg7.vhd +@@ -1,68 +1,68 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library ieee;
+-use ieee.std_logic_1164.all;
+-
+--- Convert BCD to 7-segment display characters
+-entity seg7 is
+-port (
+- D : in std_logic_vector(3 downto 0);
+- Q : out std_logic_vector(6 downto 0)
+-);
+-end seg7;
+-
+-architecture seg7_arch of seg7 is
+-begin
+- Q <= "1000000" when D = "0000" else
+- "1111001" when D = "0001" else
+- "0100100" when D = "0010" else
+- "0110000" when D = "0011" else
+- "0011001" when D = "0100" else
+- "0010010" when D = "0101" else
+- "0000010" when D = "0110" else
+- "1111000" when D = "0111" else
+- "0000000" when D = "1000" else
+- "0010000" when D = "1001" else
+- "0001000" when D = "1010" else
+- "0000011" when D = "1011" else
+- "1000110" when D = "1100" else
+- "0100001" when D = "1101" else
+- "0000110" when D = "1110" else
+- "0001110";
+-end seg7_arch;
+-
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2009-2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++ ++library ieee; ++use ieee.std_logic_1164.all; ++ ++-- Convert BCD to 7-segment display characters ++entity seg7 is ++port ( ++ D : in std_logic_vector(3 downto 0); ++ Q : out std_logic_vector(6 downto 0) ++); ++end seg7; ++ ++architecture seg7_arch of seg7 is ++begin ++ Q <= "1000000" when D = "0000" else ++ "1111001" when D = "0001" else ++ "0100100" when D = "0010" else ++ "0110000" when D = "0011" else ++ "0011001" when D = "0100" else ++ "0010010" when D = "0101" else ++ "0000010" when D = "0110" else ++ "1111000" when D = "0111" else ++ "0000000" when D = "1000" else ++ "0010000" when D = "1001" else ++ "0001000" when D = "1010" else ++ "0000011" when D = "1011" else ++ "1000110" when D = "1100" else ++ "0100001" when D = "1101" else ++ "0000110" when D = "1110" else ++ "0001110"; ++end seg7_arch; ++ +diff --git a/sn76489-1.0/sn76489_top.vhd b/sn76489-1.0/sn76489_top.vhd +index 277f601..deb8170 100644 +--- a/sn76489-1.0/sn76489_top.vhd ++++ b/sn76489-1.0/sn76489_top.vhd +@@ -196,15 +196,15 @@ begin + noise_o => noise_s + ); + +-
++ + -- Register output +- process(clock_i)
+- begin
+- if res_n_i = '0' then
+- aout_o <= (others => '0');
+- elsif rising_edge(clock_i) then
+- aout_o <= tone1_s + tone2_s + tone3_s + noise_s;
+- end if;
+- end process;
++ process(clock_i) ++ begin ++ if res_n_i = '0' then ++ aout_o <= (others => '0'); ++ elsif rising_edge(clock_i) then ++ aout_o <= tone1_s + tone2_s + tone3_s + noise_s; ++ end if; ++ end process; + + end struct; +diff --git a/vidproc.vhd b/vidproc.vhd +index 6d5f91f..25f3d75 100644 +--- a/vidproc.vhd ++++ b/vidproc.vhd +@@ -1,279 +1,279 @@ +--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- * Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- * Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- * Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC Micro "VIDPROC" Video ULA
+---
+--- Synchronous implementation for FPGA
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity vidproc is
+-port (
+- CLOCK : in std_logic;
+- -- Clock enable qualifies display cycles (interleaved with CPU cycles)
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Clock enable output to CRTC
+- CLKEN_CRTC : out std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- A0 : in std_logic;
+- -- CPU data bus (for register writes)
+- DI_CPU : in std_logic_vector(7 downto 0);
+- -- Display RAM data bus (for display data fetch)
+- DI_RAM : in std_logic_vector(7 downto 0);
+-
+- -- Control interface
+- nINVERT : in std_logic;
+- DISEN : in std_logic;
+- CURSOR : in std_logic;
+-
+- -- Video in (teletext mode)
+- R_IN : in std_logic;
+- G_IN : in std_logic;
+- B_IN : in std_logic;
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of vidproc is
+--- Write-only registers
+-signal r0_cursor0 : std_logic;
+-signal r0_cursor1 : std_logic;
+-signal r0_cursor2 : std_logic;
+-signal r0_crtc_2mhz : std_logic;
+-signal r0_pixel_rate : std_logic_vector(1 downto 0);
+-signal r0_teletext : std_logic;
+-signal r0_flash : std_logic;
+-
+-type palette_t is array(0 to 15) of std_logic_vector(3 downto 0);
+-signal palette : palette_t;
+-
+--- Pixel shift register
+-signal shiftreg : std_logic_vector(7 downto 0);
+--- Delayed display enable
+-signal delayed_disen : std_logic;
+-
+--- Internal clock enable generation
+-signal clken_pixel : std_logic;
+-signal clken_fetch : std_logic;
+-signal clken_counter : unsigned(3 downto 0);
+-
+--- Cursor generation - can span up to 32 pixels
+--- Segments 0 and 1 are 8 pixels wide
+--- Segment 2 is 16 pixels wide
+-signal cursor_invert : std_logic;
+-signal cursor_active : std_logic;
+-signal cursor_counter : unsigned(1 downto 0);
+-
+-begin
+- -- Synchronous register access, enabled on every clock
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r0_cursor0 <= '0';
+- r0_cursor1 <= '0';
+- r0_cursor2 <= '0';
+- r0_crtc_2mhz <= '0';
+- r0_pixel_rate <= "00";
+- r0_teletext <= '0';
+- r0_flash <= '0';
+-
+- for colour in 0 to 15 loop
+- palette(colour) <= (others => '0');
+- end loop;
+- elsif rising_edge(CLOCK) then
+- if ENABLE = '1' then
+- if A0 = '0' then
+- -- Access control register
+- r0_cursor0 <= DI_CPU(7);
+- r0_cursor1 <= DI_CPU(6);
+- r0_cursor2 <= DI_CPU(5);
+- r0_crtc_2mhz <= DI_CPU(4);
+- r0_pixel_rate <= DI_CPU(3 downto 2);
+- r0_teletext <= DI_CPU(1);
+- r0_flash <= DI_CPU(0);
+- else
+- -- Access palette register
+- palette(to_integer(unsigned(DI_CPU(7 downto 4)))) <= DI_CPU(3 downto 0);
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Clock enable generation.
+- -- Pixel clock can be divided by 1,2,4 or 8 depending on the value
+- -- programmed at r0_pixel_rate
+- -- 00 = /8, 01 = /4, 10 = /2, 11 = /1
+- clken_pixel <=
+- CLKEN when r0_pixel_rate = "11" else
+- (CLKEN and not clken_counter(0)) when r0_pixel_rate = "10" else
+- (CLKEN and not (clken_counter(0) or clken_counter(1))) when r0_pixel_rate = "01" else
+- (CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2)));
+- -- The CRT controller is always enabled in the 15th cycle, so that the result
+- -- is ready for latching into the shift register in cycle 0. If 2 MHz mode is
+- -- selected then the CRTC is also enabled in the 7th cycle
+- CLKEN_CRTC <= CLKEN and
+- clken_counter(0) and clken_counter(1) and clken_counter(2) and
+- (clken_counter(3) or r0_crtc_2mhz);
+- -- The result is fetched from the CRTC in cycle 0 and also cycle 8 if 2 MHz
+- -- mode is selected. This is used for reloading the shift register as well as
+- -- counting cursor pixels
+- clken_fetch <= CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2) or
+- (clken_counter(3) and not r0_crtc_2mhz));
+-
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- clken_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Increment internal cycle counter during each video clock
+- clken_counter <= clken_counter + 1;
+- end if;
+- end process;
+-
+- -- Fetch control
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- shiftreg <= (others => '0');
+- elsif rising_edge(CLOCK) and clken_pixel = '1' then
+- if clken_fetch = '1' then
+- -- Fetch next byte from RAM into shift register. This always occurs in
+- -- cycle 0, and also in cycle 8 if the CRTC is clocked at double rate.
+- shiftreg <= DI_RAM;
+- else
+- -- Clock shift register and input '1' at LSB
+- shiftreg <= shiftreg(6 downto 0) & "1";
+- end if;
+- end if;
+- end process;
+-
+- -- Cursor generation
+- cursor_invert <= cursor_active and
+- ((r0_cursor0 and not (cursor_counter(0) or cursor_counter(1))) or
+- (r0_cursor1 and cursor_counter(0) and not cursor_counter(1)) or
+- (r0_cursor2 and cursor_counter(1)));
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- cursor_active <= '0';
+- cursor_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and clken_fetch = '1' then
+- if CURSOR = '1' or cursor_active = '1' then
+- -- Latch cursor
+- cursor_active <= '1';
+-
+- -- Reset on counter wrap
+- if cursor_counter = "11" then
+- cursor_active <= '0';
+- end if;
+-
+- -- Increment counter
+- if cursor_active = '0' then
+- -- Reset
+- cursor_counter <= (others => '0');
+- else
+- -- Increment
+- cursor_counter <= cursor_counter + 1;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Pixel generation
+- -- The new shift register contents are loaded during
+- -- cycle 0 (and 8) but will not be read here until the next cycle.
+- -- By running this process on every single video tick instead of at
+- -- the pixel rate we ensure that the resulting delay is minimal and
+- -- constant (running this at the pixel rate would cause
+- -- the display to move slightly depending on which mode was selected).
+- process(CLOCK,nRESET)
+- variable palette_a : std_logic_vector(3 downto 0);
+- variable dot_val : std_logic_vector(3 downto 0);
+- variable red_val : std_logic;
+- variable green_val : std_logic;
+- variable blue_val : std_logic;
+- begin
+- if nRESET = '0' then
+- R <= '0';
+- G <= '0';
+- B <= '0';
+- delayed_disen <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Look up dot value in the palette. Bits are as follows:
+- -- bit 3 - FLASH
+- -- bit 2 - Not BLUE
+- -- bit 1 - Not GREEN
+- -- bit 0 - Not RED
+- palette_a := shiftreg(7) & shiftreg(5) & shiftreg(3) & shiftreg(1);
+- dot_val := palette(to_integer(unsigned(palette_a)));
+-
+- -- Apply flash inversion if required
+- red_val := (dot_val(3) and r0_flash) xor not dot_val(0);
+- green_val := (dot_val(3) and r0_flash) xor not dot_val(1);
+- blue_val := (dot_val(3) and r0_flash) xor not dot_val(2);
+-
+- -- To output
+- -- FIXME: INVERT option
+- if r0_teletext = '0' then
+- -- Cursor can extend outside the bounds of the screen, so
+- -- it is not affected by DISEN
+- R <= (red_val and delayed_disen) xor cursor_invert;
+- G <= (green_val and delayed_disen) xor cursor_invert;
+- B <= (blue_val and delayed_disen) xor cursor_invert;
+- else
+- R <= R_IN xor cursor_invert;
+- G <= G_IN xor cursor_invert;
+- B <= B_IN xor cursor_invert;
+- end if;
+-
+- -- Display enable signal delayed by one clock
+- delayed_disen <= DISEN;
+- end if;
+- end process;
+-end architecture;
+-
++-- BBC Micro for Altera DE1 ++-- ++-- Copyright (c) 2011 Mike Stirling ++-- ++-- All rights reserved ++-- ++-- Redistribution and use in source and synthezised forms, with or without ++-- modification, are permitted provided that the following conditions are met: ++-- ++-- * Redistributions of source code must retain the above copyright notice, ++-- this list of conditions and the following disclaimer. ++-- ++-- * Redistributions in synthesized form must reproduce the above copyright ++-- notice, this list of conditions and the following disclaimer in the ++-- documentation and/or other materials provided with the distribution. ++-- ++-- * Neither the name of the author nor the names of other contributors may ++-- be used to endorse or promote products derived from this software without ++-- specific prior written agreement from the author. ++-- ++-- * License is granted for non-commercial use only. A fee may not be charged ++-- for redistributions as source code or in synthesized/hardware form without ++-- specific prior written agreement from the author. ++-- ++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE ++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++-- POSSIBILITY OF SUCH DAMAGE. ++-- ++-- BBC Micro "VIDPROC" Video ULA ++-- ++-- Synchronous implementation for FPGA ++-- ++-- (C) 2011 Mike Stirling ++-- ++library IEEE; ++use IEEE.STD_LOGIC_1164.ALL; ++use IEEE.NUMERIC_STD.ALL; ++ ++entity vidproc is ++port ( ++ CLOCK : in std_logic; ++ -- Clock enable qualifies display cycles (interleaved with CPU cycles) ++ CLKEN : in std_logic; ++ nRESET : in std_logic; ++ ++ -- Clock enable output to CRTC ++ CLKEN_CRTC : out std_logic; ++ ++ -- Bus interface ++ ENABLE : in std_logic; ++ A0 : in std_logic; ++ -- CPU data bus (for register writes) ++ DI_CPU : in std_logic_vector(7 downto 0); ++ -- Display RAM data bus (for display data fetch) ++ DI_RAM : in std_logic_vector(7 downto 0); ++ ++ -- Control interface ++ nINVERT : in std_logic; ++ DISEN : in std_logic; ++ CURSOR : in std_logic; ++ ++ -- Video in (teletext mode) ++ R_IN : in std_logic; ++ G_IN : in std_logic; ++ B_IN : in std_logic; ++ ++ -- Video out ++ R : out std_logic; ++ G : out std_logic; ++ B : out std_logic ++ ); ++end entity; ++ ++architecture rtl of vidproc is ++-- Write-only registers ++signal r0_cursor0 : std_logic; ++signal r0_cursor1 : std_logic; ++signal r0_cursor2 : std_logic; ++signal r0_crtc_2mhz : std_logic; ++signal r0_pixel_rate : std_logic_vector(1 downto 0); ++signal r0_teletext : std_logic; ++signal r0_flash : std_logic; ++ ++type palette_t is array(0 to 15) of std_logic_vector(3 downto 0); ++signal palette : palette_t; ++ ++-- Pixel shift register ++signal shiftreg : std_logic_vector(7 downto 0); ++-- Delayed display enable ++signal delayed_disen : std_logic; ++ ++-- Internal clock enable generation ++signal clken_pixel : std_logic; ++signal clken_fetch : std_logic; ++signal clken_counter : unsigned(3 downto 0); ++ ++-- Cursor generation - can span up to 32 pixels ++-- Segments 0 and 1 are 8 pixels wide ++-- Segment 2 is 16 pixels wide ++signal cursor_invert : std_logic; ++signal cursor_active : std_logic; ++signal cursor_counter : unsigned(1 downto 0); ++ ++begin ++ -- Synchronous register access, enabled on every clock ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ r0_cursor0 <= '0'; ++ r0_cursor1 <= '0'; ++ r0_cursor2 <= '0'; ++ r0_crtc_2mhz <= '0'; ++ r0_pixel_rate <= "00"; ++ r0_teletext <= '0'; ++ r0_flash <= '0'; ++ ++ for colour in 0 to 15 loop ++ palette(colour) <= (others => '0'); ++ end loop; ++ elsif rising_edge(CLOCK) then ++ if ENABLE = '1' then ++ if A0 = '0' then ++ -- Access control register ++ r0_cursor0 <= DI_CPU(7); ++ r0_cursor1 <= DI_CPU(6); ++ r0_cursor2 <= DI_CPU(5); ++ r0_crtc_2mhz <= DI_CPU(4); ++ r0_pixel_rate <= DI_CPU(3 downto 2); ++ r0_teletext <= DI_CPU(1); ++ r0_flash <= DI_CPU(0); ++ else ++ -- Access palette register ++ palette(to_integer(unsigned(DI_CPU(7 downto 4)))) <= DI_CPU(3 downto 0); ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ -- Clock enable generation. ++ -- Pixel clock can be divided by 1,2,4 or 8 depending on the value ++ -- programmed at r0_pixel_rate ++ -- 00 = /8, 01 = /4, 10 = /2, 11 = /1 ++ clken_pixel <= ++ CLKEN when r0_pixel_rate = "11" else ++ (CLKEN and not clken_counter(0)) when r0_pixel_rate = "10" else ++ (CLKEN and not (clken_counter(0) or clken_counter(1))) when r0_pixel_rate = "01" else ++ (CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2))); ++ -- The CRT controller is always enabled in the 15th cycle, so that the result ++ -- is ready for latching into the shift register in cycle 0. If 2 MHz mode is ++ -- selected then the CRTC is also enabled in the 7th cycle ++ CLKEN_CRTC <= CLKEN and ++ clken_counter(0) and clken_counter(1) and clken_counter(2) and ++ (clken_counter(3) or r0_crtc_2mhz); ++ -- The result is fetched from the CRTC in cycle 0 and also cycle 8 if 2 MHz ++ -- mode is selected. This is used for reloading the shift register as well as ++ -- counting cursor pixels ++ clken_fetch <= CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2) or ++ (clken_counter(3) and not r0_crtc_2mhz)); ++ ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ clken_counter <= (others => '0'); ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Increment internal cycle counter during each video clock ++ clken_counter <= clken_counter + 1; ++ end if; ++ end process; ++ ++ -- Fetch control ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ shiftreg <= (others => '0'); ++ elsif rising_edge(CLOCK) and clken_pixel = '1' then ++ if clken_fetch = '1' then ++ -- Fetch next byte from RAM into shift register. This always occurs in ++ -- cycle 0, and also in cycle 8 if the CRTC is clocked at double rate. ++ shiftreg <= DI_RAM; ++ else ++ -- Clock shift register and input '1' at LSB ++ shiftreg <= shiftreg(6 downto 0) & "1"; ++ end if; ++ end if; ++ end process; ++ ++ -- Cursor generation ++ cursor_invert <= cursor_active and ++ ((r0_cursor0 and not (cursor_counter(0) or cursor_counter(1))) or ++ (r0_cursor1 and cursor_counter(0) and not cursor_counter(1)) or ++ (r0_cursor2 and cursor_counter(1))); ++ process(CLOCK,nRESET) ++ begin ++ if nRESET = '0' then ++ cursor_active <= '0'; ++ cursor_counter <= (others => '0'); ++ elsif rising_edge(CLOCK) and clken_fetch = '1' then ++ if CURSOR = '1' or cursor_active = '1' then ++ -- Latch cursor ++ cursor_active <= '1'; ++ ++ -- Reset on counter wrap ++ if cursor_counter = "11" then ++ cursor_active <= '0'; ++ end if; ++ ++ -- Increment counter ++ if cursor_active = '0' then ++ -- Reset ++ cursor_counter <= (others => '0'); ++ else ++ -- Increment ++ cursor_counter <= cursor_counter + 1; ++ end if; ++ end if; ++ end if; ++ end process; ++ ++ -- Pixel generation ++ -- The new shift register contents are loaded during ++ -- cycle 0 (and 8) but will not be read here until the next cycle. ++ -- By running this process on every single video tick instead of at ++ -- the pixel rate we ensure that the resulting delay is minimal and ++ -- constant (running this at the pixel rate would cause ++ -- the display to move slightly depending on which mode was selected). ++ process(CLOCK,nRESET) ++ variable palette_a : std_logic_vector(3 downto 0); ++ variable dot_val : std_logic_vector(3 downto 0); ++ variable red_val : std_logic; ++ variable green_val : std_logic; ++ variable blue_val : std_logic; ++ begin ++ if nRESET = '0' then ++ R <= '0'; ++ G <= '0'; ++ B <= '0'; ++ delayed_disen <= '0'; ++ elsif rising_edge(CLOCK) and CLKEN = '1' then ++ -- Look up dot value in the palette. Bits are as follows: ++ -- bit 3 - FLASH ++ -- bit 2 - Not BLUE ++ -- bit 1 - Not GREEN ++ -- bit 0 - Not RED ++ palette_a := shiftreg(7) & shiftreg(5) & shiftreg(3) & shiftreg(1); ++ dot_val := palette(to_integer(unsigned(palette_a))); ++ ++ -- Apply flash inversion if required ++ red_val := (dot_val(3) and r0_flash) xor not dot_val(0); ++ green_val := (dot_val(3) and r0_flash) xor not dot_val(1); ++ blue_val := (dot_val(3) and r0_flash) xor not dot_val(2); ++ ++ -- To output ++ -- FIXME: INVERT option ++ if r0_teletext = '0' then ++ -- Cursor can extend outside the bounds of the screen, so ++ -- it is not affected by DISEN ++ R <= (red_val and delayed_disen) xor cursor_invert; ++ G <= (green_val and delayed_disen) xor cursor_invert; ++ B <= (blue_val and delayed_disen) xor cursor_invert; ++ else ++ R <= R_IN xor cursor_invert; ++ G <= G_IN xor cursor_invert; ++ B <= B_IN xor cursor_invert; ++ end if; ++ ++ -- Display enable signal delayed by one clock ++ delayed_disen <= DISEN; ++ end if; ++ end process; ++end architecture; ++ |