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.

Bit Width using Parameters in Verilog

Status
Not open for further replies.

Ashish Agrawal

Member level 3
Joined
Mar 24, 2015
Messages
60
Helped
8
Reputation
16
Reaction score
8
Trophy points
8
Activity points
502
Hi,

I am having a memory (depth = 64, width = parameter) to be read fully and put it in a 1-D array (width = 64*memory data width). Only 1 row can be read at a time.
This is the verilog code I have written


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
parameter MEM_DATA_WIDTH = 32;
localparam DATA_WIDTH_O = 64*MEM_DATA_WIDTH;
 
reg [DATA_WIDTH_O -1 : 0] fsm_out;
wire [MEM_DATA_WIDTH -1 :0] mem_data_i;
reg [5:0] mem_addr;
 
///logic for generating mem_addr/////
//////////////////////////////////////////
 
always @ *
  begin
       if (valid_i)
         fsm_out [(mem_addr + 1)*MEM_DATA_WIDTH -1 : mem_addr *MEM_DATA_WIDTH]  <= mem_data_i;
  end




I am getting an error during compilation related to constant parameter for following operations
(mem_addr + 1)*MEM_DATA_WIDTH and mem_addr *MEM_DATA_WIDTH

Can anyone tell me how to fix this error?
Thanks in advance.
 
Last edited by a moderator:

Can anyone help me how to fix this error if it is because of inappropriate syntax?
And if it is not just a syntax error then what should I do to get that functionality in my design?

Thanks in advance.
 

Honestly you need to write good comments in your code.
What you want is to build a demultiplexer to select the 32-bit bit slice of the 64*32-bit wide fsm_out and load your 32-bit data into it.


Code Verilog - [expand]
1
2
3
4
5
6
7
// part selects take the form:
// [lower_starting_index +: width_of_slice] or
// [upper_starting_index -: width_of_slice]
// therefore....
 
fsm_out [mem_addr*MEM_DATA_WIDTH-1 +:32] = mem_data_i; // blocking assignment as this 
                                                       // is a combinational always block

 

Hi ads-ee,

Your understanding is right. But the error still exists with the following operation
mem_addr*MEM_DATA_WIDTH
As MEM_DATA_WIDTH is a constant (parameter) while mem_addr is a variable (reg).
 

I just tried the following testcase using Vivado's simulator.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module demux #(
  parameter MEM_DATA_WIDTH = 32,
  parameter DATA_WIDTH_0 = 64*MEM_DATA_WIDTH
) (
  output reg [DATA_WIDTH_0-1:0] fsm_out,
  input [MEM_DATA_WIDTH-1:0] mem_data_i,
  input [5:0] mem_addr_i,
  input clk
);
 
reg [5:0] mem_addr;
always @ (posedge clk) mem_addr <= mem_addr_i;
 
always @* begin
  fsm_out [mem_addr*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
end
endmodule


and it compiles with no errors.

What simulator (and version) are you using? I know all recent Modelsim versions support it.

You might have to resort to an ugly case statement if your simulator can't support code like above:

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
always @* begin
  case (mem_addr)
    0     : fsm_out [ 0*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
    1     : fsm_out [ 1*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
    2     : fsm_out [ 2*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
    // ...
    61    : fsm_out [61*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
    62    : fsm_out [62*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
    63    : fsm_out [63*MEM_DATA_WIDTH +:MEM_DATA_WIDTH] = mem_data_i;
  endcase
end



BTW, the -1 in the first post for the fsm_out was a typo from cutting pasting from your original post. Sorry about that.
 

But the error still exists with the following operation
mem_addr*MEM_DATA_WIDTH
Your snippet compiles correctly when changed to indexed part select.
 

What simulator (and version) are you using? I know all recent Modelsim versions support it.
I am using cadence ncsim version 14.2
It might be a simulator problem as I also remember that Modelsim supports it.

BTW, can any work around be done instead of using ugly Case statement ?
I don't want to use case statement because in future mem_addr can be 10 bit also (memory depth may change), so writing 1024 case items isn't a good idea.
 

You can check the documentation for ncsim and see if it defaults to '95 support only and you need to enable 2001 support. I'd be very surprised if it really doesn't support the part select syntax.

This code also requires Verilog 2001 support.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
integer i;
always @* begin
  for (i=0;i<64;i=i+1) begin
    if (mem_addr == i) begin
      fsm_out [i*MEM_DATA_WIDTH +: MEM_DATA_WIDTH] = mem_data_i;
    end
  end
end


The for loop should unroll into identical code with the other versions.

You talk about this being memory, but this code probably doesn't synthesize to a memory. It doesn't conform to any standard inferred memory template. The standard templates use an array.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top