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 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
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;
+