Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to use generate statement Verilog?

er.akhilkumar

Full Member level 2
Joined
Feb 1, 2011
Messages
121
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,298
Location
Noida
Activity points
2,422
I need to generate some register in Register Map using generate statement. Here is the code:

reg [31:0];

always @ (posedge clk or negedge rst_n)

begin

if (!rst_n)

reg <= P_REG_RSTVAL;

else if (wr_en && add == P_REG_ADDR)

reg <= data_in;

end



If I have a parameter P_NUM_REG which specifies the number of registers and I also have reset value and reg address parameters with naming convention P_REG0_RSTVAL and P_REG0_ADDR respectively, how I can use generate statement here?

Please help.
 
If your code is really this simple, I would use a script to generate it externally. verilog generate statements have limitations and it can be annoying to use.
 
There are multiple ways to do this.

Yes, you can use a generate here, the problem is all you can do is generate the blocks in a loop. Then you need to connect them and that can be just as messy as not doing anything at all.
You could also use a script, this is nice to quickly put something almost bug free, but the problem I had here is often people forget of the script, lose it, make manual changes on the output, then someone regenerates the file and wipes away changes and so on. Another problem with register scripts is you often have one or two registers that just do not fit the standard writing way, like, for example, some complex write-only reg that initiates some state.

So for register files I usually use macros. Then all simple registers, perhaps 90% of then, are coded by macros and the few more complex ones I just write the RTL for them.

Ex:
I create a set of modules, one for each register type: rwreg, roreg, rwregpl (rw reg with parallel load).
I specify a format. Each register should have a parameter with its address, one with the default value, and one with a mask (if a bit is 1 it is valid if it is 0 it is not valid). Then I define the ins/outs. Each one needs a clock, write enable, write value, address, and then two outputs, a val (current value), and a rdata (current value if addr == ADDR parameter or 0 if it does not match).

Here is a simple example of a r/w reg...
module rwreg #(ADDRS = ..., ) (input clk, input rst_n, ....)
reg [31:0] regis;

// here would be a simple R/W reg. Note that the MASK is anded with the data in and data out. This makes sure synthesis will wipe away unused bits.
always @(posedge clk or negedge rst_n)
if (!rst_n) regis <= DEF
else if (wr_en && addr == ADDRS) regis <= datin & MASK;
end
// val is the current value. rdata is the value if the register is selected, or zero otherwise.
assign val = regis & MASK;
assign rdata = (addr == ADDRS) ? regis & MASK : 32'd0;


Then I create a macro, one for each type. Here is an example using Verilog2001:
' define REGPLACE (inst, rdo, val, ADDRS, DEFS, MASKS) \
rwreg \
#(.ADDR(ADDRS), .DEF(DEFS), .MASK(MASKS)) name(.clk(CLK), .datin(data_in), .addr(addr), .wr(wr_en), .rdata(rdo), .val(val));
' define ROREGPLACE(...
...

Then just instantiate them together with any register mapped signals:
' REGPLACE(i_rstval, rstval_rdata, rstval, RSTVAL_ADDR, RSTVAL_DEF)
assign rstval_rst = rstval[RSTVAL_RST_Pos];
...
' REGPLACE(i_someotherreg, someotherreg, someotherreg_val, SOMEOTHERREG_ADDR, SOMEOTHERREG_DEF)
' REGPLACERO(...)
...

If you have SystemVerilog you can reduce this a bit because of the doubletick:
'define REGPLACE(name, NAME) \
rwreg #(.ADDR(NAME''_ADDR), .DEF(NAME''_DEF), .MASK(NAME''_MASK) i_name (.clk(CLK), .datin(data_in), .addr(addr), .wr(wr_en), .rdata(name''_rdata), .val(name));
...
then instantiate:
' REGPLACE(rstval, RSTVAL)
' REGPLACE(someotherreg, SOMEOTHERREG)
...


Next you connect all lines to your output read cone. Note that because we use the address to enable the rdata lines to be non-zero, we then can simply OR them all together as only one will be non-zero:
assign prdata =
rstval_rdata |
someotherreg_rdata |
...

And you might want to undef the macros at the end of the file to not conflit with other files:
' undef RWREG
...


Finally you create a file with the defaults. This one I often use a simple script, but it can be done by hand. The nice here is this part is usually very consistent so the script can be quite simple. Just put a major warning for people to not change the file by hand or someone will slap the culprits silly,
parameter RSTVAL_ADDR = 12'h000
parameter RSTVAL_DEF = 32'h00000000
parameter RSTVAL_MASK = 32'h00000001
parameter RSTVAL_RST_Pos = 0;
parameter SOMEOTHERREG_ADDR = 12'h004
parameter SOMEOTHERREG_DEF = 32'h00000000
...
 
Last edited:

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top