// Toplevel module of the FPGA implementation of a 64K byte Philips P856 minicomputer. // This module integrates the CPU/CU module with the Console Controler and Memory, // as well as the JTAG interface, which takes care of the link to a Personal Computer. // // Name : P8-023 // Version: 023 // Date : 03-01-2012 // Author : Theo Engel // Contact: Info@theoengel.nl // The toplevel module, integrating the CPU, RAM, Control, etc. Also defines the interface signals // of the FPGA to the development board. These signals must be assigned to pins of the FPGA. // // version 011: initial version // version 012: memory controller able to address bytes // version 013: working P856 // version 014: just some editing (not used) // version 015: used in sdcard tryouts // version 016: low level sdcard interface added (device 0x11) // version 017: adds X1215 support based on an sdcard (disk read) // version 018: PR register resets now to address /FFFF // version 018a: leds display CR output iso CR input // version 019: cleanup; remove sd-card test interface // version 020: add ptp // version 021: add ptr // version 022: fptr state from green leds // version 023: disk-offset register added (03-01-2012) module P856 ( // interface signals / pins //////////////////// Clock Input //////////////////// CLOCK_24, // 24 MHz //CLOCK_27, // 27 Mhz //CLOCK_50, // 50 MHz //////////////////// Push Buttons //////////////////// KEY, // Pushbutton[3:0] //////////////////// Switch //////////////////// SW, // Toggle Switch[9:0] //////////////////// 7-SEG Display //////////////////// HEX0, // Seven Segment Digit 0 HEX1, // Seven Segment Digit 1 HEX2, // Seven Segment Digit 2 HEX3, // Seven Segment Digit 3 //////////////////////// LEDs //////////////////////// LEDG, // LED Green[7:0] LEDR, // LED Red[9:0] //////////////////// SRAM Interface //////////////// SRAM_DQ, // SRAM Data bus 16 Bits SRAM_ADDR, // SRAM Address bus 18 Bits SRAM_UB_N, // SRAM High-byte Data Mask SRAM_LB_N, // SRAM Low-byte Data Mask SRAM_WE_N, // SRAM Write Enable SRAM_CE_N, // SRAM Chip Enable SRAM_OE_N, // SRAM Output Enable //////////////////// SD_Card Interface //////////////// SD_DAT, // SD Card Data 0 (DO on card) SD_DAT3, // SD Card Data 3 (CS on card) SD_CMD, // SD Card Command Signal (DI in card) SD_CLK, // SD Card Clock (CK on card) //////////////////// USB JTAG link //////////////////// TDI, // CPLD -> FPGA (data in) TCK, // CPLD -> FPGA (clk) TCS, // CPLD -> FPGA (CS) TDO // FPGA -> CPLD (data out) ); // Development Board Interface //////////////////////// Clock Input //////////////////////// input [1:0] CLOCK_24; // 24 MHz // //input [1:0] CLOCK_27; // 27 MHz // //input CLOCK_50; // 50 MHz //////////////////////// Push Button //////////////////////// input [3:0] KEY; // Pushbutton[3:0] //////////////////////// Switch //////////////////////// input [9:0] SW; // Toggle Switch[9:0] //////////////////////// 7-SEG Dispaly //////////////////////// output [6:0] HEX0; // Seven Segment Digit 0 output [6:0] HEX1; // Seven Segment Digit 1 output [6:0] HEX2; // Seven Segment Digit 2 output [6:0] HEX3; // Seven Segment Digit 3 //////////////////////////// LED //////////////////////////// output [7:0] LEDG; // LED Green[7:0] output [9:0] LEDR; // LED Red[9:0] //////////////////////// SRAM Interface //////////////////////// inout [15:0] SRAM_DQ; // SRAM Data bus 16 Bits output [17:0] SRAM_ADDR; // SRAM Address bus 18 Bits output SRAM_UB_N; // SRAM High-byte Data Mask output SRAM_LB_N; // SRAM Low-byte Data Mask output SRAM_WE_N; // SRAM Write Enable output SRAM_CE_N; // SRAM Chip Enable output SRAM_OE_N; // SRAM Output Enable //////////////////////// USB JTAG link ///////////////////////// input TDI; // CPLD -> FPGA (data in) input TCK; // CPLD -> FPGA (clk) input TCS; // CPLD -> FPGA (CS) output TDO; // FPGA -> CPLD (data out) //////////////////// SD_Card Interface //////////////// inout SD_DAT; // SD Card Data (SPI: DO output on card) inout SD_DAT3; // SD Card Data 3 (SPI: CS, chip select input on card) inout SD_CMD; // SD Card Command Signal (SPI: DI input on card) output SD_CLK; // SD Card Clock (SPI: Clock input on card) wire SD_DATi; // SD_DAT is tristated but only used for input assign SD_DAT = 1'bz; assign SD_DATi = SD_DAT; //////////////////////////////////////////////////////////////////// // USB JTAG wire [7:0] mRXD_DATA,mTXD_DATA; wire mRXD_Ready,mTXD_Done,mTXD_Start; wire mTCK; // SRAM: use the 1st 32K words; so the address range is [14:0]. // The SRAM addresses words of 16 bit, so the 32 k words represent // the 64 k bytes of the P856 memory. The P856 uses 16 bit memory // addresses ! wire [14:0] oSR_ADDR; // 15 bit word address (32k word memory) wire [15:0] oSR_DATA_TO_RAM, iSR_DATA_FROM_RAM; wire oSR_OE_N, oSR_WE_N; wire oSR_UB_N, oSR_LB_N; assign oSR_UB_N = 1'b0; // SRAM word access assign oSR_LB_N = 1'b0; // SRAM word access // SEG7 * 4 wire [15:0] mSEG7_DIG; wire Clock; assign Clock = CLOCK_24[1]; //assign Clock = CLOCK_50; ////////////////////////////////////////////////////////////////////////////// // Wiring between CPU Registers/Switches and the CPU,Console and CPU-Console Muxes // Register scratchpad wiring wire [15:0] oR1, oR2; // register scratchpad output wire [15:0] oPC, oA1, oA2, oA3, // register scratchpad output oA4, oA5, oA6, oA7, oA8, oA9, oA10, oA11, oA12, oA13, oA14, oA15; wire [15:0] mRi, iRi_CPU, iRi_CON; // register scratchpad input wire [3:0] mR_A1, iR_A1_CPU, iR_A1_CON, iR_A2_CPU; // address of register to read wire [3:0] mR_WRA, iR_WRA_CPU, iR_WRA_CON; // address of register to write wire mR_WR, iR_WR_CPU, iR_WR_CON; // register write enable signals wire iPC_INC_CPU, iA15_INC_CPU, iA15_DEC_CPU; // PC/A15 incr/decr signals // Wiring Break Point register wire [15:0] oPR,iPR; wire mPR_WR; // Wiring Disk-offset register wire [15:0] oDO,iDO; wire mDO_WR; // Wiring instruction register wire [15:0] mIR_CPU; // Wiring PSW wire [15:0] mPSW_CPU; /////////////////////////////////////////////////////////////////////////////// // Peripheral wiring between Console (with simulated peripheral support) and the CPU with the Control units wire mf_SWS; // TTY wire mTIRq,mTORq,mTIRy,mTORy; wire [7:0] mTCI, mTCO; // PTR wire mPIRq,mPIRy,mPTry,mFPTR; //wire [3:0] mFptr_ST; //wire [2:0] PTR_ST; wire [7:0] mPCI; // PTP wire mPtpO,mPORy; wire [7:0] mPCO; // Console Switches/CPU Control and Registers // mCpuActive: activated by the CPU when an instruction is executed (after a Run or Step) // reset after execution of HLT or a single step or honoration of a Stop request by the Console) // mCpuStop: Console requests the CPU to stop (honored by the CPU when CpuActive = 1) wire mCpuStep; // Single Step signal to the cpu (Console signal) wire mCpuRun; // Run signal to the cpu (Console signal) wire mCpuActive; // 1 => CPU is running (CPU signal) wire mCpuEnb; // 1 => Interrupt is enabled (CPU signal) wire mCpuPil0; // Standard Interrupt Line (CPU signal) wire mCpuError; // 1 => CPU is in Error state (CPU signal) wire mCpuStop; // Stop signal to the cpu (Console signal) wire mCpuCP; // Panel Interrupt signal (Console signal) wire mCpuClkSw; // Panel Clock switch wire mMasterClear_n; // Master Clear signal to the cpu, registers, etc. (Console signal) // Registers (either controled by the Console or the Console and CPU) // Breakpoint register (set by Console) r_pr PR(.iClk(Clock), .oQ(oPR), .iD(iPR), .iLoad(mPR_WR), .iReset_n(mMasterClear_n)); // Disk Offset Register (set by Console) register #(16) DO(.iClk(Clock), .oQ(oDO), .iD(iDO), .iLoad(mDO_WR), .iReset_n(mMasterClear_n)); // Register Scratchpad (16x16) reg_file REG(.iClk(Clock), .iReset_n(mMasterClear_n), // register outpout .oQ1(oR1) , .oQ2(oR2), .oPC(oPC) , .oA1(oA1) , .oA2(oA2) , .oA3(oA3), .oA4(oA4) , .oA5(oA5) , .oA6(oA6) , .oA7(oA7), .oA8(oA8) , .oA9(oA9) , .oA10(oA10), .oA11(oA11), .oA12(oA12), .oA13(oA13), .oA14(oA14), .oA15(oA15), // register input .iD(mRi), .iRa1(mR_A1), .iWr_a(mR_WRA), .iWr_en(mR_WR), .iRa2(iR_A2_CPU), // register increment/decrement signals .iPCi2(iPC_INC_CPU), .iA15i2(iA15_INC_CPU), .iA15d2(iA15_DEC_CPU)); // Muxes to select the register input either from CPU or from the Console // (input for iRa2, iPCi2, iA15i2, iA15d2 only coming from the CPU) assign mRi = mCpuActive ? iRi_CPU : iRi_CON; // Input of register being loaded assign mR_WRA = mCpuActive ? iR_WRA_CPU : iR_WRA_CON; // Address of register being loaded assign mR_WR = mCpuActive ? iR_WR_CPU : iR_WR_CON; // Write enable for register being loaded assign mR_A1 = mCpuActive ? iR_A1_CPU : iR_A1_CON; // Address of register being read // Wiring between RAM and the CPU, Console and CPU-Console Muxes wire [15:0] iSR_DATA_CPU, iSR_DATA_CON; wire [14:0] iSR_ADDR_CPU, iSR_ADDR_CON; wire iSR_OE_CPU_N, iSR_OE_CON_N; wire iSR_WE_CPU_N, iSR_WE_CON_N; // Muxes to select the input for the RAM (either from the CPU or Console) assign oSR_DATA_TO_RAM = mCpuActive ? iSR_DATA_CPU : iSR_DATA_CON; assign oSR_ADDR[14:0] = mCpuActive ? iSR_ADDR_CPU : iSR_ADDR_CON; assign oSR_OE_N = mCpuActive ? iSR_OE_CPU_N : iSR_OE_CON_N; assign oSR_WE_N = mCpuActive ? iSR_WE_CPU_N : iSR_WE_CON_N; ////////////////////////////////////////////////////////////////////////////// wire [1:0] mCpuCR; wire mCpuOv; wire mX1215Rdy; assign LEDG[0] = mX1215Rdy; // displays whether the 2 disk units are operational assign LEDG[2:1] = mCpuCR; // displays CR assign LEDG[3] = mCpuOv; // displays Overflow bit assign LEDG[4] = mCpuPil0; // displays the interrupt line status assign LEDG[5] = mCpuEnb; // displays whether the Interrupt is enabled or not assign LEDG[6] = mCpuError; // displays whether the CPU entered an error condition assign LEDG[7] = mCpuActive; // displays whether the CPU is active or not assign LEDR[0] = SD_CLK; assign LEDR[1] = SD_DAT3; // cs assign LEDR[2] = mFPTR; // 1 if FPTR selected; assign LEDR[4:3] = 2'b00; //assign LEDR[0]= mFPTR; //assign LEDR[3:1] = PTR_ST; //assign LEDR[7:4] = mFptr_ST; assign LEDR[8:5] = mIR_CPU[14:11]; // opcode assign LEDR[9] = mMasterClear_n; // Off: Master Clear Signal == 1 // display register content on the 4 * 7-segment leds // register to display is selected by 4 toggle switches wire [4:0] mRadrSW = SW[9:5]; assign mSEG7_DIG = (mRadrSW == 5'b00000) ? oPC : (mRadrSW == 5'b00001) ? oA1 : (mRadrSW == 5'b00010) ? oA2 : (mRadrSW == 5'b00011) ? oA3 : (mRadrSW == 5'b00100) ? oA4 : (mRadrSW == 5'b00101) ? oA5 : (mRadrSW == 5'b00110) ? oA6 : (mRadrSW == 5'b00111) ? oA7 : (mRadrSW == 5'b01000) ? oA8 : (mRadrSW == 5'b01001) ? oA9 : (mRadrSW == 5'b01010) ? oA10 : (mRadrSW == 5'b01011) ? oA11 : (mRadrSW == 5'b01100) ? oA12 : (mRadrSW == 5'b01101) ? oA13 : (mRadrSW == 5'b01110) ? oA14 : (mRadrSW == 5'b01111) ? oA15 : oPC; // MasterClear by one of the push buttons wire mReset_n; assign mReset_n = KEY[0] & KEY[1] & KEY[2] & KEY[3]; ////////////////////////////////////////////////////////////////////////////// // 4 digit display for the Program Counter SEG7_4 d4 (HEX0,HEX1,HEX2,HEX3,mSEG7_DIG ); // Controller for the CPU Console functions and for the link with the Personal Computer P8_Control con (// USB JTAG .iRXD_DATA(mRXD_DATA),.iRXD_Ready(mRXD_Ready), .oTXD_DATA(mTXD_DATA),.oTXD_Start(mTXD_Start),.iTXD_Done(mTXD_Done), // SRAM interface with the console .iSR_DATA(iSR_DATA_FROM_RAM),.oSR_DATA(iSR_DATA_CON),.oSR_ADDR(iSR_ADDR_CON), .oSR_WE_N(iSR_WE_CON_N),.oSR_OE_N(iSR_OE_CON_N), // CPU interface with the Console .iR(oR1), .iPC(oPC), .iA15(oA15), .oR_RDA(iR_A1_CON), // read scratchpad .oR(iRi_CON), .oR_WRA(iR_WRA_CON), .oR_WRE(iR_WR_CON), // write scratchpad .iIR(mIR_CPU), // instruction register .iPSW(mPSW_CPU), // PSW //// CPU Control .oRun(mCpuRun), .oStep(mCpuStep), .oStop(mCpuStop), .oCP(mCpuCP), .oClkSw(mCpuClkSw), .oMC_n(mMasterClear_n), .iRunning(mCpuActive), .iError(mCpuError), .iEnb(mCpuEnb), .iPR(oPR), .oPR(iPR), .oPR_WR(mPR_WR), // break point register .iDO(oDO), .oDO(iDO), .oDO_WR(mDO_WR), // disk-offset register //// Peripheral interfaces // TTY .TtyCharIn(mTCI), .iTtyInReq(mTIRq), .oTtyIChar(mTIRy), .iTty(mTCO), .iTtyCharO(mTORq), .oTtyOutReady(mTORy), // PTR .iPtrInReq(mPIRq),.oPtrIChar(mPIRy),.PtrCharIn(mPCI),.iPtrTry(mPTry),.f_FPTR(mFPTR), // PTP .iPtp(mPCO),.iPtpO(mPtpO),.oPtpOutReady(mPORy), // Control .iCLK(Clock),.iRST_n(mReset_n), .of_SWS(mf_SWS)); // 32k 16 bit words memory controller (the sram itself is on the development board) Sram ram (// Host .oHS_DATA(iSR_DATA_FROM_RAM),.iHS_DATA(oSR_DATA_TO_RAM),.iHS_ADDR({3'b000,oSR_ADDR}), .iHS_WE_N(oSR_WE_N),.iHS_OE_N(oSR_OE_N), .iHS_UB_N(oSR_UB_N), .iHS_LB_N(oSR_LB_N), // SRAM .SRAM_DQ(SRAM_DQ), .SRAM_ADDR(SRAM_ADDR), .SRAM_UB_N(SRAM_UB_N), .SRAM_LB_N(SRAM_LB_N), .SRAM_WE_N(SRAM_WE_N), .SRAM_CE_N(SRAM_CE_N), .SRAM_OE_N(SRAM_OE_N)); // P856 CPU and control units P856_CPU cpu (.iClk(Clock), // Scratchpad .oA(iRi_CPU), .oRa1(iR_A1_CPU), .oRwra(iR_WRA_CPU), .oRwr(iR_WR_CPU), .oRa2(iR_A2_CPU), .oPCi2(iPC_INC_CPU), .oA15i2(iA15_INC_CPU), .oA15d2(iA15_DEC_CPU), .iR1(oR1), .iR2(oR2), .oPSW(mPSW_CPU), .oIR(mIR_CPU), .iPC(oPC) , .iA1(oA1) , .iA2(oA2) , .iA15(oA15), // SRAM .iMbr(iSR_DATA_FROM_RAM), .oMbr(iSR_DATA_CPU), .oMaddr(iSR_ADDR_CPU), .oM_we_n(iSR_WE_CPU_N), .oM_oe_n(iSR_OE_CPU_N), // Control .iRun(mCpuRun), .iStep(mCpuStep), .iStop(mCpuStop), .iCP(mCpuCP), .iClkSw(mCpuClkSw), .iMC_n(mMasterClear_n), .oRunning(mCpuActive), .oError(mCpuError), .oEnb(mCpuEnb), .oPil(mCpuPil0), .if_SWS(mf_SWS), .iPR(oPR), .oCR(mCpuCR), .oOv(mCpuOv), // TTY .TtyCharIn(mTCI), .oTtyInReq(mTIRq), .iTtyIChar(mTIRy), .oTty(mTCO), .oTtyCharO(mTORq), .iTtyOutReady(mTORy), // PTP .oPtpO(mPCO), .oPtpCharO(mPtpO), .iPtpOutReady(mPORy), // PTR .oPtrInReq(mPIRq), .iPtrIChar(mPIRy), .PtrCharIn(mPCI), .oPtrTry(mPTry), // SD-Card .oSdClk(SD_CLK) , .oSdCS(SD_DAT3), .oSdDO(SD_CMD), .iSdDI(SD_DATi), .MdOperational(mX1215Rdy), .offset(oDO)); // JTAG Clock (Altera module, in Altera supplied file CLK_LOCK.v) CLK_LOCK cl (.inclk(TCK),.outclk(mTCK)); // JTAG link with the Personal Computer (Altera module, in Altera supplied file USB_JTAG.v) USB_JTAG u1 (// HOST .iTxD_DATA(mTXD_DATA),.oTxD_Done(mTXD_Done),.iTxD_Start(mTXD_Start), .oRxD_DATA(mRXD_DATA),.oRxD_Ready(mRXD_Ready),.iRST_n(mReset_n),.iCLK(Clock), // JTAG .TDO(TDO),.TDI(TDI),.TCS(TCS),.TCK(mTCK)); endmodule // General Register module module register (iClk,oQ,iD,iLoad,iReset_n); parameter width = 16; input iClk,iReset_n,iLoad; input [width-1:0] iD; output reg [width-1:0] oQ; always @ (posedge iClk or negedge iReset_n) begin if(! iReset_n) begin oQ<=0; end else if(iLoad) begin oQ<=iD; end end endmodule // Breakpoint Register // resets to memory address ffff because reset to 0000 would stop the cpu when address 0 is used // and addres 0 is used by the ipl from disk program module r_pr (iClk,oQ,iD,iLoad,iReset_n); input iClk,iReset_n,iLoad; input [15:0] iD; output reg [15:0] oQ; always @ (posedge iClk or negedge iReset_n) begin if(! iReset_n) begin oQ<=16'hFFFF; //reset to FFFF, the highest memory address end else if(iLoad) begin oQ<=iD; end end endmodule // register file to implement the 16 scratchpad registers A0..A15 module reg_file(iClk, iReset_n, oQ1, oQ2, oPC, oA1, oA2, oA3, oA4, oA5, oA6, oA7, oA8, oA9, oA10, oA11, oA12, oA13, oA14, oA15, iD, iRa1, iRa2, iPCi2, iA15i2, iA15d2, iWr_a, iWr_en); input wire iClk, iReset_n, iWr_en; // clock, reset, register write enable input wire iPCi2, iA15i2, iA15d2; // incr PC by 2, incr A15 by 2,decr A15 by 2 input wire [3:0] iRa1,iRa2; // addresses of registers to read input wire [3:0] iWr_a; // address of register to write input wire [15:0] iD; // register (addressed by iWa and enabled by iWen) input output wire [15:0] oQ1, oQ2; // register output (register selected by iRa1,iRa2) output wire [15:0] oPC, oA1, oA2, oA3, oA4, oA5, oA6, oA7, oA8, oA9, oA10, oA11, oA12, oA13, oA14, oA15; // output of each individual register (e.g. for display) reg [15:0] R [15:0]; // 16 16 bit registers parameter PC = 4'h0; // register addresses parameter A0 = 4'h0; parameter A1 = 4'h2; parameter A2 = 4'h4; parameter A3 = 4'h6; parameter A4 = 4'h8; parameter A5 = 4'hA; parameter A6 = 4'hC; parameter A7 = 4'hE; parameter A8 = 4'h1; parameter A9 = 4'h3; parameter A10 = 4'h5; parameter A11 = 4'h7; parameter A12 = 4'h9; parameter A13 = 4'hB; parameter A14 = 4'hD; parameter A15 = 4'hF; // two adressed registers can be read in parallel (e.g. as input for an ALU) by iRa1 and iRa2 // the output of the individual register is also available (eg. for display) assign oQ1 = R[iRa1]; assign oQ2 = R[iRa2]; assign oPC = R[A0]; // program counter assign oA1 = R[A1]; assign oA2 = R[A2]; assign oA3 = R[A3]; assign oA4 = R[A4]; assign oA5 = R[A5]; assign oA6 = R[A6]; assign oA7 = R[A7]; assign oA8 = R[A8]; assign oA9 = R[A9]; assign oA10 = R[A10]; assign oA11 = R[A11]; assign oA12 = R[A12]; assign oA13 = R[A13]; assign oA14 = R[A14]; assign oA15 = R[A15]; always @ (posedge iClk or negedge iReset_n) begin if(! iReset_n) begin R[A0] <= 16'h0000; // reset all registers R[A1] <= 16'h0000; R[A2] <= 16'h0000; R[A3] <= 16'h0000; R[A4] <= 16'h0000; R[A5] <= 16'h0000; R[A6] <= 16'h0000; R[A7] <= 16'h0000; R[A8] <= 16'h0000; R[A9] <= 16'h0000; R[A10] <= 16'h0000; R[A11] <= 16'h0000; R[A12] <= 16'h0000; R[A13] <= 16'h0000; R[A14] <= 16'h0000; R[A15] <= 16'h0000; end else begin if(iWr_en) R[iWr_a] <= iD; else if(iPCi2) R[A0] <= oPC + 2'b10; // increment program counter else if(iA15i2) R[A15] <= oA15 + 2'b10; // increment A15 else if(iA15d2) R[A15] <= oA15 - 2'b10; // decrement A15 end end endmodule // Memory controller module (the sram itself is on the development board) // The sram addresses words while byte access is controlled with the ub and lb signals // The P856 uses 16 bit byte addresses module Sram( // Host oHS_DATA, //data to host iHS_DATA, //data from host iHS_ADDR, //address from host iHS_WE_N, //write enable iHS_OE_N, //read enable iHS_UB_N, //upper byte enable iHS_LB_N, //lower byte enable // SRAM SRAM_DQ, SRAM_ADDR, SRAM_UB_N, SRAM_LB_N, SRAM_WE_N, SRAM_CE_N, SRAM_OE_N ); // Host interface input [17:0] iHS_ADDR; input [15:0] iHS_DATA; output [15:0] oHS_DATA; input iHS_WE_N; input iHS_OE_N; input iHS_UB_N; input iHS_LB_N; // SRAM interface inout [15:0] SRAM_DQ; output [17:0] SRAM_ADDR; output SRAM_UB_N, SRAM_LB_N, SRAM_WE_N, SRAM_CE_N, SRAM_OE_N; assign SRAM_DQ = SRAM_WE_N ? 16'hzzzz : iHS_DATA ; assign oHS_DATA = SRAM_DQ ; assign SRAM_ADDR = iHS_ADDR; assign SRAM_WE_N = iHS_WE_N; assign SRAM_OE_N = iHS_OE_N; assign SRAM_CE_N = 1'b0; // chip always enabled assign SRAM_UB_N = iHS_UB_N; assign SRAM_LB_N = iHS_LB_N; endmodule // This module implements the 4 digits of the seven segment hexadecimal display on the development board. // The display is used to show the content of the Program Counter module SEG7_4 ( oSEG0,oSEG1,oSEG2,oSEG3,iDIG ); input [15:0] iDIG; output [6:0] oSEG0,oSEG1,oSEG2,oSEG3; SEG7 d0 (oSEG0,iDIG[3:0]); SEG7 d1 (oSEG1,iDIG[7:4]); SEG7 d2 (oSEG2,iDIG[11:8]); SEG7 d3 (oSEG3,iDIG[15:12]); endmodule // One seven segment hexadecimal digit. module SEG7 (oSEG,iDIG); input [3:0] iDIG; output [6:0] oSEG; reg [6:0] oSEG; // Each segment ia addresses by a bit // in a 7-bit bit string, where bits are // numbered as follows: // 6 5 4 3 2 1 0 // A segment is ON when its bit in the // bitstring is 0 (and OFF when its bit is 1). // Segments and bits correspond as follows: // --0-- // | | // 5 1 // | | // --6-- // | | // 4 2 // | | // --3-- // The 16 hexadecimal digits blink with the following // bitstrings: always @(iDIG) begin case(iDIG) 4'h1: oSEG = 7'b1111001; 4'h2: oSEG = 7'b0100100; 4'h3: oSEG = 7'b0110000; 4'h4: oSEG = 7'b0011001; 4'h5: oSEG = 7'b0010010; 4'h6: oSEG = 7'b0000010; 4'h7: oSEG = 7'b1111000; 4'h8: oSEG = 7'b0000000; 4'h9: oSEG = 7'b0011000; 4'ha: oSEG = 7'b0001000; 4'hb: oSEG = 7'b0000011; 4'hc: oSEG = 7'b1000110; 4'hd: oSEG = 7'b0100001; 4'he: oSEG = 7'b0000110; 4'hf: oSEG = 7'b0001110; 4'h0: oSEG = 7'b1000000; endcase end endmodule