What does data_mux mean here? Is it just a name for the block?
if ((PORT_CONFIG == "32") && (P0 == 1'b1))
begin : data_mux
...
end
These are block names. Especially useful with generate blocks. For example you can define a generate block such as
genvar i;
generate (for i = 0; i<10; i++)
begin : structures
reg my_reg;
// ...
.. other block descriptions
// ...
end
endgenerate
Then you can access the block elements later like
structures[3].my_reg <= 1'b1;
Yes, it is just the name for the begin/end block. Refer to the free IEEE Std 1800-2012 (section 9.3.4 Block names). In most cases the block label is optional.
Related
I want to generate my register interface, because I have several instance (channels) of the same peripheral.
while (I < generic_num_of_instances) loop
case loc_addr is
when 0 + I*256 =>
q_ctrl_reg(I, 31 downto 0) <= s_axi_wdata;
end case;
I := I + 1;
end loop;
And it says: Error: Case choice must be locally static expression.
How can I generate this register interface? Should I use less descriptive if/elseif statements?
Matthew mentioned two important improvements, your case target must be a static expression (whose type is a locally static type) and if you are doing synthesis, you need to use a for loop.
Next, you cannot slice a multi-dimensional array, hence, q_ctrl_reg(I, 31 downto 0) is also invalid. Lets fix that by using an array of an array (shown below):
type q_ctrl_reg_type is array (0 to MAX_REG -1) of std_logic_vector(31 downto 0) ;
signal q_ctrl_reg : q_ctrl_reg_type ;
Now lets put it all together, lets us a for loop instead of the while loop and an if statement instead of your case statement:
for i in 0 to generic_num_of_instances - 1 loop
if loc_addr = 0 + I*256 then
q_ctrl_reg(I) <= s_axi_wdata;
end if;
end loop;
Yes. Or use Verilog.
Case choices is VHDL have to be locally static - that is they have to be literals, constants or generics. That isn't the case with Verilog.
You're also going to find that you need a when others branch, which will negate any improved readability gained using a case statement. (And given such a coding style is rather unusual anyway, I'd question whether it was ever more readable.)
try making that "0 + I*256" value equal to a variable that you name in the loop i.e.
while (I < generic_num_of_instances) loop
variable A : integer;
begin
A := 0 + I*256;
case loc_addr is
when A =>
q_ctrl_reg(I, 31 downto 0) <= s_axi_wdata;
end case;
I := I + 1;
end loop;
hopefully this should work
I having trouble with finding the smallest values of X and xfind and Y and yfind in `Costcalculator xfind (X,xcost);
Costcalculator yfind (Y,ycost);
in code below.
can someone comment please. For some reason I couldn't import the whole code. It just recognizes these lines as codes. Sorry if it is not clear.
always #(posedge clk) // sequential circuit
begin
Costcalculator xfind (X,xcost);
Costcalculator yfind (Y,ycost);
if(reset)
begin
i=0;
R<=0;
xcost<=0;
ycost<=0;
mode0<=0;
mode1<=0;
mode2<=0;
mode3<=0;
mode4<=0;
mode5<=0;
mode6<=0;
end //if end
else
begin
for (i=1; i<43; i=i+1)
begin
R<=xcost+ycost;
costholder <= SAD+(lambda*R); // Here we calculate the cost of a sub-blocks As the clock
if (i<17)
mode0<=costholder+mode0;
else if(i>16 && i<25)
mode1<=costholder+mode1;
else if(i>24 && i<33)
mode2<=costholder+mode2;
else if(i==33 || i==34 || i==35 || i==36 )
mode3<=costholder+mode3;
else if(i==37 || i==38)
mode4<=costholder+mode4;
else if(i==39 || i==40)
mode5<=costholder+mode5;
else if(i==41)
mode6<=costholder+mode6;
end //for end
end //else end
end //always end
Module Costcalculator:
//************************************************************
module Costcalculator (motionvector, cost); // X AND Y COST CALCULATOR
input [4:0]motionvector;
output [2:0]cost;
reg [2:0]cos;
wire [3:0] vector;
assign vector = {motionvector[3:0] };
always #* begin
case (vector) 0 : cos=0;
1,2 : cos=1;
3,4,5,6 : cos=2;
7,8,9,10,11,12,13,14 : cos=3;
15 : cos=4;
endcase
end
assign cost = cos;
endmodule
//************************************************************
After taking the module outside the always block, you are driving xconst and yconst from two places. On the other hand, I don't see drivers of X and Y.
Since Costcalculator is a purely combinational module, you need to just provide the inputs X and Y as zero from the top/wrapper module.
//.. some stuff
if(reset) begin
//... some other signals
X <= 0;
Y <=0;
//...
As the error says about multiple drivers, you are driving xconst and yconst form two modules. On reset, if you provide X and Y as 0 from the wrapping module, then automatically the vector will go to Zero and ultimately the cost which is the output of module will become Zero. Thereby the variables xconst and yconst will become zero.
Refer to this similar forum question for more information.
I have a problem with the code below. The code is synthesized in ISE 14.2.
input [1:8176] m_d_in;
reg [1:511] m_d [1:16];
integer i;
always # (*)
begin
for (i=0; i<16; i=i+1)
begin
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
end
after synthesizing, this error shows up:
HDL Compiler:1660_<'Address of CodeName.v> <'Line of Error>: procedural assignment to a non-register i is not permitted, left-hand side should be reg/integer/time/genvar
the line of Error refer to this:
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
i also have tested using the:
reg [4:0] i;
and
genvar i;
instead of:
integer i;
and got exactly the same error I wrote above!
I know there is a solution by using a case instead of the code above, but in its not the right solution for me.
Thanks a lot.
Since you are range is consistent, Indexing vectors and arrays with +: is also possible:
always #* begin
for (i=0; i<16; i=i+1)
m_d[i+1] = m_d_in[511*i+1 +: 511];
end
The indexed part select (+:/-:) and generate block (from Morgan's answer) were introduced in IEEE std 1364-2001. Any modern simulator and synthesizer will support them.
If you use wire instead of reg then a single assign line can be wrapped up in a generate.
module tb(
input [1:8176] m_d_in
);
wire [1:511] m_d [1:16];
genvar i;
generate
for (i=0; i<16; i=i+1) begin
assign m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
endgenerate
endmodule
To keep the reg and use generates you would need to do:
module tb(
input [1:8176] m_d_in
);
reg[1:511] m_d [1:16];
genvar i;
generate
for (i=0; i<16; i=i+1) begin
always #* begin
m_d[i+1] = m_d_in[ 1+511*i : 511+511*i];
end
end
endgenerate
endmodule
In a generate loop, you often need to connect the first iteration of wires to your inputs (or some unique set of wires) before the array stuff kicks in. Pasted below is a snippet from my parameterizable OR-Reduce module (my assignment requires structural verilog, so oOUt = |adjA is not legal).
for(i=0; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
if(i==0) begin
or2$ reduce [oWidth-1:0]
(tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
end else begin
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
end
I have to put this nasty if-statement to catch the first iteration and connect it to the inputs. The problem is that I can't just change the initial i value to 1 and declare a lvl[0].tmp outside of the for-loop. Here's what I think would look nicer if it were legal.
wire [p2Width-1] lvl[0].tmp;
or2$ reduce [oWidth-1:0]
(lvl[0].tmp, adjA[iWidth/2-1:0], adjA[iWidth-1:iWidth/2]);
for(i=1; i<depth; i=i+1) begin : lvl
localparam iWidth = p2Width>>i;
localparam oWidth = iWidth>>1;
wire [oWidth-1:0] tmp;
or2$ reduce [oWidth-1:0]
(tmp, lvl[i-1].tmp[iWidth/2-1:0], lvl[i-1].tmp[iWidth-1: iWidth/2]);
end
Is there a way to clean up my generate loop?
You can declare your input array to be one entry wider than required. I find this often results in more readable code:
logic [N_LEVELS:0] block_inputs; // Last entry not used, optimised away
logic [N_LEVELS-1:0] block_outputs;
// Start of pipeline
assign block_inputs[0] = stage1_input;
genvar i;
generate
for (i=0; i<N_LEVELS; i++) begin: levels
some_block i_some_block (
.data (block_inputs[i]),
.result (block_outputs[i])
);
assign block_inputs[i+1] = block_outputs[i];
end
endgenerate
assign final_result = block_outputs[N_LEVELS-1];
I need to randomize a large memory. All of the data is contained inside of latch modules -- 1 per bit.
How do I fix the following?
// Quick mock up of the memory, which I can't change
`define WIDTH 64*144
module latch(
output reg Q);
endmodule
module memory;
wire [`WIDTH-1:0] latchData;
latch latch[`WIDTH-1:0] (.Q(latchData[`WIDTH-1:0]));
endmodule
// My testbench, which I can change
module test;
reg [31:0] index;
memory memory();
initial begin
$display("Initial data: %0d", memory.latchData);
injectRandomData();
$display("Randomized data: %0d", memory.latchData);
end
task injectRandomData();
// Using for loop does not work
//for (index=0; index < `WIDTH; index = index+1) begin
// memory.latch[index].Q = $urandom;
//end
// Doing it this way seems terrible
memory.latch[0].Q = $urandom;
memory.latch[1].Q = $urandom;
memory.latch[2].Q = $urandom;
// ... a bunch more to go; don't wait up
endtask
endmodule
Code on EDA Playground: http://www.edaplayground.com/s/4/235
Quick and dirty solution:
task injectRandomData();
->do_InjectRandomData;
#0; // gen always block a change to finish;
endtask
event do_InjectRandomData;
genvar index;
generate
for(index = 0; index < `WIDTH; index = index +1) begin : gen_loop
always #(do_InjectRandomData) begin : set_rand
memory.latch[index].Q = $urandom;
end
end
endgenerate
Code on EDA Playground: http://www.edaplayground.com/s/6/236
You cannot dynamically index an array of instances. Two ways to fix this:
Do you really need to model a memory at such a low level? Change the memory model to an RTL description. It will be much better for performance anyways.
Use a generate block with a for-loop around the initial block instead of a for-loop inside the initial block. If you need to do this at some time other than time 0 you can use an event to trigger it.
genvar index;
event injectRandomData;
for (index=0; index < `WIDTH; index++) begin
always #injectRandomData
memory.latch[index].Q = $urandom;
end