In Verilog, is there a way to pass a Parameter value from a top_level project into the lower modules?
Or at this point must it become a register?
n00b Verilog Questions
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: n00b Verilog Questions
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.
The instantiation of one of the UARTs in the top-level module
The definition of the UART module. Some parameters are passed down to other instantiated sub-modules such as the transmit and receive FIFO modules.
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.
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: Select all
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
);
Code: Select all
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()
);
Code: Select all
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
);
Michael A.
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: n00b Verilog Questions
Thanks Michael, that does help to a degree. In my situation I have 'wires' in the top_level that use the parameter values as well, so when I try applying what you did in your example to my case, I get an error "such&such is not a constant".
You seem to pass the parameter values from a module to the top_level, then to other modules. I think I need something that will pass a parameter value from the top_level to other modules.
You seem to pass the parameter values from a module to the top_level, then to other modules. I think I need something that will pass a parameter value from the top_level to other modules.
Re: n00b Verilog Questions
EEyE:
I declare the parameters for both the top module and any sub-modules at the start of the top module. I can then use the testbench to modify these parameters to test specific configurations. I do this so that by reading the parameter settings of the top module I can determine/recall how the top module and the sub-modules are configured for a particular synthesis/MAP/PAR session.
The ISE command line can be used to define macro and set parameter values. Thus, I expect, although I've never attempted to do this, that I can modify the parameters in a compile/synthesis script and parameterize the complete project without any edits to the source files. There's a limited capability to do this in the GUI, but that capability is what I use to configure/command Data2MEM to modify the contents of the block RAMs for the M65C02/M16C5x soft-core projects.
Look into the operation of the defparam keyword. It appears to be used by Xilinx to directly modify parameters within a sub-module without going through the top module. I've come across examples of its use in most of the IP that CoreGen produces.
I am not clear on the issue that you are experiencing. parameters are treated as constants as far as I know. For you to be getting that error indicates to me that you are trying to use a variable to determine vector indices in some way.
I am not a power use of Verilog 2001, but it appears to have some specific constructs to allow accessing various parts of a vector. I dropped in on stackoverflow.com and saw an example of such a construct. The question was posed as something like: "what does vector[8:i] do?"
I declare the parameters for both the top module and any sub-modules at the start of the top module. I can then use the testbench to modify these parameters to test specific configurations. I do this so that by reading the parameter settings of the top module I can determine/recall how the top module and the sub-modules are configured for a particular synthesis/MAP/PAR session.
The ISE command line can be used to define macro and set parameter values. Thus, I expect, although I've never attempted to do this, that I can modify the parameters in a compile/synthesis script and parameterize the complete project without any edits to the source files. There's a limited capability to do this in the GUI, but that capability is what I use to configure/command Data2MEM to modify the contents of the block RAMs for the M65C02/M16C5x soft-core projects.
Look into the operation of the defparam keyword. It appears to be used by Xilinx to directly modify parameters within a sub-module without going through the top module. I've come across examples of its use in most of the IP that CoreGen produces.
ElEctric_EyE wrote:
In my situation I have 'wires' in the top_level that use the parameter values as well, so when I try applying what you did in your example to my case, I get an error "such&such is not a constant".
I am not a power use of Verilog 2001, but it appears to have some specific constructs to allow accessing various parts of a vector. I dropped in on stackoverflow.com and saw an example of such a construct. The question was posed as something like: "what does vector[8:i] do?"
Michael A.
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: n00b Verilog Questions
I will investigate, that's good info. Thanks for passing your findings along!
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: n00b Verilog Questions
................................
Today I was looking back at some Verilog code written for the orsoc graphics accelerator which has been posted in the Arithmetic Core Section on opencores.org. I had first started learning Verilog from this project years ago and have built my current project around the structure of the state machine that I had found in the gfx_line module. Back then I was trying to learn Bresenham Line...
After comparing that module to some of the other modules in that project today, I had noticed that one of the comments of another module of identical construction to the one I currently use for all my graphic accelerated functions, that said it was a Mealy machine. I had heard of Mealy/Moore state machines before but knew nothing of them.
So now something clicked and I immediately knew (at least I think I do!) what the difference is between the two.
In a Mealy state machine it takes inputs into consideration and when state machine tells an output to change state during a rising edge of a CLK, it actually happens on the following rising edge as if it were a flip flop. I've noticed this in my simulations, especially when I was nailing down exact timing on the back to back Read/Write functions of the Sync RAM I'm using.
In a Moore state machine, there are no inputs?, but when an output signal is assigned a value it changes during that state as if it were a latch.
Is this correct thinking?
Today I was looking back at some Verilog code written for the orsoc graphics accelerator which has been posted in the Arithmetic Core Section on opencores.org. I had first started learning Verilog from this project years ago and have built my current project around the structure of the state machine that I had found in the gfx_line module. Back then I was trying to learn Bresenham Line...
After comparing that module to some of the other modules in that project today, I had noticed that one of the comments of another module of identical construction to the one I currently use for all my graphic accelerated functions, that said it was a Mealy machine. I had heard of Mealy/Moore state machines before but knew nothing of them.
So now something clicked and I immediately knew (at least I think I do!) what the difference is between the two.
In a Mealy state machine it takes inputs into consideration and when state machine tells an output to change state during a rising edge of a CLK, it actually happens on the following rising edge as if it were a flip flop. I've noticed this in my simulations, especially when I was nailing down exact timing on the back to back Read/Write functions of the Sync RAM I'm using.
In a Moore state machine, there are no inputs?, but when an output signal is assigned a value it changes during that state as if it were a latch.
Is this correct thinking?