This is not a blocker that I'm dealing with, just looking for possibly a more elegant way of doing it.
module Ram(RamClk, CKE, CAS, RAS, WE, DQM, BA, A, DQ,
OpEnable, Addr, RdData, WrData, Ready);
input RamClk;
output CKE;
output logic CAS, RAS, WE;
output [1:0] DQM;
output logic [1:0] BA;
output logic [11:0] A;
inout [15:0] DQ;
input OpEnable;
output [23:0] Addr; //24 bits = 16 Mb
output [15:0] RdData;
input [15:0] WrData;
output Ready;
// code omitted here
wire CMD = {CAS,RAS,WE};
// code omitted here
//multiplexers
always #*
begin
if (InitDone == 0)
begin
CMD = InitCmd;
A = InitA;
BA = InitBA;
end
else
begin
//todo: assign the output of the main CMD, A and BA multiplexers
CMD = CMD_NOP;
A = 0;
BA = 0;
end
end
//rest of the module
I have 3 outputs of the module RAS, CAS, WE that I'm combining into a single wire for convenience so that I can assign command values to them as a whole.
Now I need to connect a multiplexer to CMD and I'm doing it in an always block for convenience.
I could do it in separate assign statements in this case of only 2 inputs to the multiplexer using the ternary expression, but let's imagine the multiplexer has more inputs, for more inputs it looks more convenient to use multiple if/else or a case statement which I cannot use with assign as far as I understand.
Now I have an issue that I have to have a reg on the LHS in the always block although it is combinatorial logic in this case and it will not infer a register in this case.
But if I change CMD to reg then I cannot use the {} notation to combine CAS, RAS and WE.
I could replace the CMD with a task or combine/split CAS, RAS and WE outside the module and have them as a single CMD module parameter.
Any more elegant way of expressing this?
When you have have multiple variables that you would like to assign at once, you can use the concatenation operator on the LHS of an expression:
output logic CAS, RAS, WE;
...
logic [2:0] CMD;
assign {CAS, RAS, WE} = CMD;
...
CMD = 3'b011; // Will assign CAS = 0, RAS = 1, WE = 1
...
You can also just not use CMD at all and just use {CAS, RAS, WE} in its place; depending on your style and what makes sense for your project. A side note, ideally, you should be using always_comb over always #(*) and logic over wire and reg (mostly) if you are in a SystemVerilog environment as you seem to be.
Related
I am writing assertions in system verilog. This assertion check for a signal "lock" which is passed as an test argument through switch $value$plusargs as GPIO_SEL="test_bench.gpio"
So my code is :
module ab
string abc;
$value$plusargs("GPIO_SEL=%s" , abc);
reg lock;
always #*
begin
lock = abc;
end
endmodule
The problem here is that signal lock is not getting value as test_bench.gpio. Is there any way i can pass this signal value from testplaus args
SystemVerilog is a compiled language, not interpreted. You can't access identifiers directly using a string. You can use compiler directives on the command line
module ab;
bit lock;
always_comb
begin
lock = `GPIO_SEL;
end
endmodule
Then when compiling your code use a +define switch
vlog your_file.sv +define+GPIO_SEL=test_bench.gpio
If you think re-compiling your testbench/dut is a significant burden (most tools offer incremental compilation options), and you have a fixed number of paths to access, then you can use a case statement
module ab
string abc;
initial $value$plusargs("GPIO_SEL=%s" , abc);
reg lock;
always_comb
case (abc)
"test_bench.gpio": lock = test_bench.gpio;
"test_bench.gpio1": lock = test_bench.gpio1;
endcase
end
And you could just use a simple number instead of a string to select.
Looks like you need to conver the string to an integer type. Look at the string conversion functions: atoi, atobin, ...
for example
module parg;
string abc;
bit [3:0] sig;
initial begin
$value$plusargs("GPIO_SEL=%s" , abc);
sig = abc.atoi();
$display("sig = %b", sig);
end
endmodule // parg
I have a bunch of signals like this:
logic [7:0] in0;
logic [7:0] in1;
logic [7:0] in2;
logic [7:0] in3;
That I want to assign to an array:
logic [7:0] in_array [4];
assign in_array[0] = in0;
assign in_array[1] = in1;
assign in_array[2] = in2;
assign in_array[3] = in3;
Easy enough, but if instead of 4 items I have 128 this gets annoying. I am sure there is a combination of defines and generates that can do this in a loop. Something like:
`define IN(x) inx
genvar i;
generate
for(i = 0; i<4; i++) begin
assign in_array[i] = `IN(i);
end
endgenerate
The above code doesn't work, but I think that I have done something like this before.
Simplifying that code is something that cannot be done in SystemVerilog. You can reduce you typing by creating a macro like below (note the double backticks ``), but you will still need to manually write each index. Macros are are resolved before generate loops and the input variable to the macro is treated as a literal.
// short named macro for reduced typing
// Note: using short named macro is typically a bad practice,
// but will be removed latter with an undef
`define A(idx) assign array_in[idx] = out``idx
//This works
`A(0);
`A(1);
`A(2);
`A(3);
// doesn't work. For example # gidx==0 will eval to 'assign array_in[0] = outgidx;'.
// There is not outgidx
genvar gidx;
generate
for(gidx=0; gidx<4; gidx++) begin
`A(gidx);
end
endgenerate
`undef A // prevent macro from from being used latter on
If it is just a small number of entries, it is best to do it manually. If it is large number of entries, then you need to consider a way to generate the for you, such as embedded coded.
There are also various embedded code (such as Perl's EP3, Ruby's eRuby/ruby_it, Python's prepro, etc.) that can generate the desired code. Pick your preference. You will need to per-process these files before giving to the compiler. Example with EP3 generating 400 assignments:
#perl_begin
foreach my $idx (0..400) {
printf "assign array_in[%0d] = out%0d;", $idx, $idx;
}
#perl_end
Use `` to separate text from argument.
`define IN(x) in``x
But there is another issue with the variable i not being declared at the time when the macro is evaluated. Thus the whole generate loop just connects to ini, because i is just another letter. Because of this macros cannot be assigned by dynamically allocated values.
The environment of your module already has to connect explicitly to each input assign in0 = out0; ... assign in127 = out127. So the simplest solution would be to have in_array as your modules input and let the environment connect to it assign array_in[0] = out0.
Something like this:
module parent_module();
/*some other stuff that has outputs out0, out1 etc.*/
logic [7:0] array_in[4];
assign array_in[0] = out0;
assign array_in[1] = out1;
assign array_in[2] = out2;
assign array_in[3] = out3;
my_module(.array_in(array_in));
endmodule
I created a module to soemthing simple like add some pipeline delay. I made the data type a parameter so it could handle complex things like structs. I have something like this:
module pipe
#(parameter type T = int,
parameter DELAY = 0)
(
input clk,
input T data_in,
output T data_out);
T pipe[DELAY];
always_ff #(posedge clk) begin
pipe[0] <= data_in;
for(int i = 1; i<DEPTH; i++) begin
pipe[i] <= pipe[i-1];
end
end
assign data_out = pipe[DELAY-1];
endmodule
This works great but then I found myself wanting to use it with an unpacked array and I couldn't figure out how to instance it. It would look something like this, but I don't think this is right:
logic [7:0] my_data [16];
logic [7:0] my_data_delayed [16];
pipe #(.T(logic [7:0] [16]), .DELAY(2)) i_pipe
(
.clk(clk),
.data_in(my_data),
.data_out(my_data_delayed)
);
Is there a way to get the type of a variable so it can be passed to this parameter?
You can use typedef do define the data type:
typedef logic [7:0] my_type [16];
my_type my_data;
my_type my_data_delayed;
pipe #(.T(my_type), .DELAY(2)) i_pipe
(
.clk(clk),
.data_in(my_data),
.data_out(my_data_delayed)
);
The remaining question is if it will work with your simulator. I tried it out at EDAplayground, worked with VCS but not Riviera-PRO (got a "not supported in this release" message)
I was able to get typedef struct { logic [7:0] data [16]; } my_type; to work. Less clean but it is a workaround.
While typing the question I figured out one answer. The type operator (section 6.23 in IEEE 1800-2012) spec does what I need. So my instance would look like this:
logic [7:0] my_data [16];
logic [7:0] my_data_delayed [16];
pipe #(.T(type(my_data)), .DELAY(2)) i_pipe
(
.clk(clk),
.data_in(my_data),
.data_out(my_data_delayed)
);
Of course this results in a compile error in my tool so it doesn't look to be universally supported.
My work-around is going to be to make an array of instances of the pipe module.
Suppose that all input wires except one is supposed to be in Hi-Z. We want to connect these wires into a single wire (e.g. data bus). How can this be done in SystemVerilog?
If you mean module inputs, the alias construct can do this:
module a(input wire a,b,c);
wire bus; // use if you want a different internal name
alias a = b = c = bus;
endmodule
I'm sure this will not be synthesizable.
Assuming your condition that only one input is not Z holds true then we could just loop through and find the last non-Z input and assign its value to the output. No idea if this would synthesize.
module merge_bus
#(parameter BUSW = 8)
(
input [BUSW-1:0] bus_in,
output wire_out
);
always_comb begin
wire_out = 1'bz;
for(int i = 0; i<BUSW; i++) begin
if(bus_in[i] !== 1'bz) wire_out = bus_in[i];
end
end
endmodule
You can make use of wor/wand data types from verilog.
I'm trying to synthesize an Altera circuit using as few logic elements as possible. Also, embedded multipliers do not count against logic elements, so I should be using them. So far the circuit looks correct in terms of functionality. However, the following module uses a large amount of logic elements. It uses 24 logic elements and I'm not sure why since it should be using 8 + a couple of combinational gates for the case block.
I suspect the adder but I'm not 100% sure. If my suspicion is correct however, is it possible to use multipliers as a simple adder?
module alu #(parameter N = 8)
(
output logic [N-1:0] alu_res,
input [N-1:0] a,
input [N-1:0] b,
input [1:0] op,
input clk
);
wire [7:0] dataa, datab;
wire [15:0] result;
// instantiate embedded 8-bit signed multiplier
mult mult8bit (.*);
// assign multiplier operands
assign dataa = a;
assign datab = b;
always_comb
unique case (op)
// LW
2'b00: alu_res = 8'b0;
// ADD
2'b01: alu_res = a + b;
// MUL
2'b10: alu_res = result[2*N-2:N-1]; // a is a fraction
// MOV
2'b11: alu_res = a;
endcase
endmodule
Your case statement will generate a 4 input mux with op as the select which uses a minimum of 2 logic cells. However since your assigning an 8-bit variable in the case block you will require 2 logic elements for each bit of the output. Therefore total logic elements is 8*2 for the large mux and 8 for the adder giving you 24 as the total.
I'm doing this project too so I won't give too much away about how to optimise this. However what I will tell you is that both the mux's and the adder can be implemented using multipliers, 8 at most. With that said I don't think this architecture is optimal for a multiplier implementation.