EEyE:
I am sure that there must be a more effective way than the way that I use, but for me, it is a reliable method.
In a lower level module, I use the
parameter keyword to define various parameters that allow me to define desired configurations. In the top most module, I define a similar parameter, and pass that down through all of the instantiated sub-modules to the desired sub-modules.
The
defparam keyword may also be used. It can be used to reach all the way to the desired sub-module using the hierarchical path name of the sub-module. It can be used from the top-level module.
The following three code segments illustrate the method that I use for passing parameters from the top-level module to sub-modules. The first code segment is the parameters in my Dual Core M65C02 top level module, the second is instantiation of one of the UART sub-modules, and the third is the definition of the UART sub-module.
Code:
module M65C02Duo #(
parameter pIRQ_Vector = 16'hFFFE, // Maskable Interrupt Vector
parameter pBRK_Vector = 16'hFFFE, // BRK Instruction Trap Vector
parameter pRST_Vector = 16'hFFFC, // Reset Vector
parameter pNMI_Vector = 16'hFFFA, // Non-Maskable Interrupt Vector
parameter pStkPtr_Rst = 8'hFF, // Stk Ptr Value after Reset
parameter pInt_Hndlr = 9'h021, // _Int microroutine address
parameter p_uP_AddrWidth = 8'd9,
parameter p_uP_Width = 8'd36,
parameter p_uP_Init = "Src/M65C02_uPgm_V3b.coe",
parameter pDEC_AddrWidth = 8'd8,
parameter pDEC_Width = 8'd36,
parameter pDEC_Init = "Src/M65C02_IDEC_v3.coe",
parameter pMMU_A_Init = "Src/M65C02_MMU_CPU0.coe", // MMU Init. File
parameter pMMU_B_Init = "Src/M65C02_MMU_CPU1.coe", // MMU Init. File
parameter pRAM_A_AddrWidth = 8'd14, // 16384 x 8 Block RAM
parameter pROM_A_AddrWidth = 8'd11, // 2048 x 8 Block RAM
parameter pRAM_B_AddrWidth = 8'd13, // 8192 x 8 Block RAM
parameter pROM_B_AddrWidth = 8'd11, // 2048 x 8 Block RAM
parameter pBus_Width = 8'd8, // Bus Width = 8 bits
parameter pRAM_A_Init = "Src/65C02_ft.txt", // Functional Test Pgm
parameter pROM_A_Init = "Src/Mon6502_sbc25.txt", // (0xFFFC)=0x0400
parameter pRAM_B_Init = "Src/M65C02_Tst6.txt", // Here: JMP Here
parameter pROM_B_Init = "Src/Mon6502_sbc25.txt", // (0xFFFC)=0x0400
parameter pFrequency = 29491200, // (14.7456 MHz * 2)
parameter pDefault_LCR_A = 8'h40, // ~BRRE, RTSo, 232 w/o HS, 8N1
parameter pDefault_IER_A = 8'h00, // No interrupts enabled
parameter pBaudrate_A = 115200,
parameter pRTOChrDlyCnt_A = 3, // RTO asserted on Rx idle 3 char times
parameter pTF_Depth_A = 0, // Tx FIFO Depth = (2**(0+4))=16
parameter pRF_Depth_A = 0, // Rx FIFO Depth = (2**(0+4))=16
parameter pTF_Init_A = "Src/UART_TF_16.coe",
parameter pRF_Init_A = "Src/UART_RF_16.coe",
parameter pDefault_LCR_B = 8'h40, // ~BRRE, RTSo, 232 w/o HS, 8N1
parameter pDefault_IER_B = 8'h00, // No interrupts enabled
parameter pBaudrate_B = 115200,
parameter pRTOChrDlyCnt_B = 3, // RTO asserted on Rx idle 3 char times
parameter pTF_Depth_B = 0, // Tx FIFO Depth = (2**(0+4))=16
parameter pRF_Depth_B = 0, // Rx FIFO Depth = (2**(0+4))=16
parameter pTF_Init_B = "Src/UART_TF_16.coe",
parameter pRF_Init_B = "Src/UART_RF_16.coe",
parameter pDefault_CR = 8'h30, // Rate=1/16, Mode=0, Dir=MSB, Sel=0
parameter pSPI_FIFO_Depth = 8'd4, // Depth = (1 << 4) = 16
parameter pSPI_FIFO_Init = "Src/SPI_FIFO_Init_16.coe"
)(
input nRst, // System Reset Input
input ClkIn, // System Clk Input
output nRstO, // Internal System Reset Output (OC w/ PU)
// M65C02 Clock Outputs
output Phi2O, // Clock Phase 2 Output
output Phi1O, // Clock Phase 1 Output - complement of Phi2O
// M65C02 External Bus Enable
input BE_In, // Bus Enable: tri-states address, data, control
// M65C02 Special Interface Signals
//input nSO, // Set oVerflow: currently unimplemented
output nWAI, // Driven low by Wait instruction (ASIC-only)
// M65C02 External Interrupt Bus
input nNMI, // Non-Maskable Interrupt Request: edge sense
input nIRQ, // Maskable Interrupt Request: level sense
output nVP, // Vector Pull: asserted to indicate ISR taken
// M65C02 Memory Interface Bus
output Sync, // Synchronize: asserted during opcode fetch
output nML, // Memory Lock: asserted during RMW instructions
output [3:0] nCE, // Chip Enable for External RAM/ROM Memory
output RnW, // Read/nWrite cycle control output signal
output nOE, // External Asynchronous Bus
output nWE, // External Asynchronous Bus Write Strobe
inout Rdy, // Bus cycle Ready, drive low to extend cycle
output [ 3:0] XA, // Extended Address Output for External Memory
output [15:0] A, // External Memory Address Bus
inout [ 7:0] DB, // External, Bidirectional Data Bus
// M65C02 Asynchronous Serial Port Interface
output reg TxD_A, // Port A: Transmit Serial Data (Common 232/485)
input RxD_A, // Port A: Receive Serial Data (AND Rx232/Rx485)
output reg nRTS_A, // Port A: Ready To Send Flow Control Output
input nCTS_A, // Port A: Clear To Send Flow Control Input
output reg DE_A, // Port A: RS485 Drive Enable
output reg TxD_B, // Port B: Transmit Serial Data (Common 232/485)
input RxD_B, // Port B: Receive Serial Data (AND Rx232/Rx485)
output reg nRTS_B, // Port B: Ready To Send Flow Control Output
input nCTS_B, // Port B: Clear To Send Flow Control Input
output reg DE_B, // Port B: RS485 Drive Enable
// M65C02 SPI Port Interface
output [1:0] nCSO, // SPI I/F Chip Select
output SCK, // SPI I/F Serial Clock
output MOSI, // SPI I/F Master Out/Slave In Serial Data
input MISO, // SPI I/F Master In/Slave Out Serial Data
// Non-65C02 Special Interface Signals
output nCore, // nCSO[2]: 0 (On) - Core 1; 1 (Off) - Core 0
input nWP // Internal Boot/Monitor RAM write protect
);
The instantiation of one of the UARTs in the top-level module
Code:
UART #(
.pFrequency(pFrequency),
.pDefault_LCR(pDefault_LCR_A),
.pDefault_IER(pDefault_IER_A),
.pBaudrate(pBaudrate_A),
.pRTOChrDlyCnt(pRTOChrDlyCnt_A),
.pTF_Depth(pTF_Depth_A),
.pRF_Depth(pRF_Depth_A),
.pTF_Init(pTF_Init_A),
.pRF_Init(pRF_Init_A)
) COM_A (
.Rst(Rst),
.Clk(Clk),
.IRQ(COM_A_IRQ),
.Sel(COM_A_CE),
.Reg(PA_A[1:0]),
.RE(Rd_A),
.WE(Wr_A),
.DI(DO_A),
.DO(COM_A_DO),
.TxD_232(TxD_232_A),
.RxD_232(rRxD_A),
.xRTS(RTS_A),
.xCTS(CTS_A),
.TxD_485(TxD_485_A),
.RxD_485(rRxD_A),
.xDE(iDE_A),
.TxIdle(),
.RxIdle()
);
The definition of the UART module. Some parameters are passed down to other instantiated sub-modules such as the transmit and receive FIFO modules.
Code:
module UART #(
// Default UART Settings
parameter pDefault_LCR = 8'h80, // RTSo, Tx Enable, 232 w/o HS, 8N1
parameter pDefault_IER = 8'h00, // All interrupts disabled
// Default UART Baud Rate Settings
parameter pFrequency = 29491200, // 29.4912 MHz
parameter pBaudrate = 115200, // 115200 bps
// Default Receive Time Out Character Delay Count
parameter pRTOChrDlyCnt = 3, // Default Number of Characters for RTO
// FIFO Configuration Parameters
parameter pTF_Depth = 0, // Tx FIFO Depth: 2**(TF_Depth + 4)
parameter pRF_Depth = 0, // Rx FIFO Depth: 2**(RF_Depth + 4)
parameter pTF_Init = "Src/UART_TF_16.coe", // Tx FIFO Memory Initialization
parameter pRF_Init = "Src/UART_RF_16.coe" // Rx FIFO Memory Initialization
)(
input Rst, // System Reset
input Clk, // System Clock
// External Interrupt Request
output reg IRQ, // Interrupt Request
// Parallel Interface
input Sel, // UART Select
input [1:0] Reg, // UART Register Select
input RE, // UART Read Strobe
input WE, // UART Write Strobe
input [7:0] DI, // UART Data Input Bus
output wor [7:0] DO, // UART Data Output Bus
// External UART Interface
output TxD_232, // RS-232 Mode TxD
input RxD_232, // RS-232 Mode RxD
output reg xRTS, // RS-232 Mode RTS (Ready-To-Receive)
input xCTS, // RS-232 Mode CTS (Okay-To-Send)
output TxD_485, // RS-485 Mode TxD
input RxD_485, // RS-485 Mode RxD
output xDE, // RS-485 Mode Transceiver Drive Enable
// TxSM/RxSM Status
output TxIdle, // UART TxSM Idle Status Output
output RxIdle // UART RxSM Idle Status Output
);
Hope this helps. I find that determining the parameterization that should be applied to a particular IP module is difficult. Too much parameterization leads to code that is hard to read, and an insufficient amount leads to code difficult to adapt without error prone edits to multiple applications. I generally develop the module first, and then I add parameterization.