I'm new in SystemVerilog, and currently learn interfaces, and I ran into problem with structural modules.
So, for example, i have created interface
interface BusInterface
#(parameter N = 3) (input logic i_clk);
logic i_RESET;
logic i_in;
logic counterClock;
logic[(N - 1):0] o_count;
logic o_ERROR;
modport DetectorInterface
(input i_RESET,
input i_in,
output counterClock,
output o_ERROR);
modport CounterInterface
(input i_RESET,
output o_count);
modport FallingsCounterInterface
(input i_RESET,
input i_in,
output o_count,
output o_ERROR);
modport StimulatorInterface
(output i_RESET,
output i_in,
input o_count);
modport MonitorInterface
(input i_RESET,
input i_in,
input counterClock,
input o_count,
input o_ERROR);
modport CommonInterface
(input i_RESET);
endinterface
I also created 2 modules:
module FallingEdge_Detector
(BusInterface.DetectorInterface interfaceDetector);
int k;
typedef enum logic[1:0] {s_NewCountCycle, s_ReadyToCount, s_EndCountCycle} stateType;
stateType currentState, nextState;
// Register logic
always_ff #(posedge interfaceDetector.i_clk, posedge interfaceDetector.i_RESET)
begin
if (interfaceDetector.i_RESET) currentState <= s_NewCountCycle;
else if (interfaceDetector.i_clk) currentState <= nextState;
end
// Next State logic
always_comb
begin
case (currentState)
s_NewCountCycle:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_NewCountCycle;
end
s_ReadyToCount:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_EndCountCycle;
end
s_EndCountCycle:
begin
if (interfaceDetector.i_in) nextState <= s_ReadyToCount;
else nextState <= s_NewCountCycle;
end
endcase
end
// Output logic
assign interfaceDetector.counterClock = (currentState == s_EndCountCycle);
assign interfaceDetector.o_ERROR = (currentState != s_EndCountCycle) &
(interfaceDetector.counterClock == 1'b1);
endmodule
module Counter
#(parameter N = 3) (BusInterface.CounterInterface interfaceCounter);
int k;
// Register logic
always_ff #(posedge interfaceCounter.i_clk, posedge interfaceCounter.i_RESET)
begin
if (interfaceCounter.i_RESET) k <= 0;
else if (interfaceCounter.i_clk) k <= k + 1;
end
// Output logic
assign interfaceCounter.o_count = k[(N - 1):0];
endmodule
The problem is that I cannot create a top-level module:
module FallingsCounter
#(parameter N = 3) (BusInterface.FallingsCounterInterface interfaceFallingsCounter);
/*
(input logic i_clk, i_RESET,
input logic i_in,
output logic[(N - 1):0] o_count,
output logic o_ERROR);
*/
logic counterClock;
FallingEdge_Detector Detector
(interfaceFallingsCounter.i_clk, interfaceFallingsCounter.i_RESET,
interfaceFallingsCounter.i_in,
counterClock,
interfaceFallingsCounter.o_ERROR);
Counter Counter
(counterClock, interfaceFallingsCounter.i_RESET,
interfaceFallingsCounter.o_count);
endmodule
When I try to make this in that way, i get the next errors:
Error (10285): Verilog HDL Module Instantiation error at FallingsCounter.sv(28): instance "Detector" specifies 5 actual port connections but module "FallingEdge_Detector" only expects 1
Error (10978): SystemVerilog error at FallingsCounter.sv(25): unknown type and interface type are not equivalent - equivalent types must have same number of bits
Error (10698): SystemVerilog error at FallingsCounter.sv(25): can't connect expression with incompatible data type to formal "interfaceDetector"
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(25): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(26): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(27): too many ports used in Module Instantiation
Error (10181): Verilog HDL Module Instantiation error at FallingsCounter.sv(28): too many ports used in Module Instantiation
So, I have the question: how to create the top level module using interface?
You can't use modports in your top-level module port declaration unless they are going to be connected to the same modport in the lower level modules.
Modports are like sub-types passed through an interface port. They define access rights to a bundle of signals, and you cannot change the modport type one it is passed into the module.
What you can do is pass the full interface (without modports) through the top-level module
Related
I'm trying to build a RegisterFile that utilizes these 3 components. I just don't know how to put them all together. I have the start of the register file module but just have no clue how to top end it. Is there any way anyone could explain, I'm just so lost. I also think there may be an issue with my Register module. I really am a novice with verilog, so I'm very confused on most things.
module Decoder3To8(input enable, input[2:0] in, output[7:0] out);
assign d[0]=(~a[2])&(~a[1])&(~a[0]);
assign d[1]=(~a[2])&(~a[1])&(a[0]);
assign d[2]=(~a[2])&(a[1])&(~a[0]);
assign d[3]=(~a[2])&(a[1])&(a[0]);
assign d[4]=(a[2])&(~a[1])&(~a[0]);
assign d[5]=(a[2])&(~a[1])&(a[0]);
assign d[6]=(a[2])&(a[1])&(~a[0]);
assign d[7]=(a[2])&(a[1])&(a[0]);
endmodule
module Register4Bit(input clock, input clear, input load, input[3:0] in, output reg[3:0] out);
always#(negedge clock or posedge clear)
begin
if(clear)
out<=4′b0000;
else
out[3]<=out[2];
out[2]<=out[1];
out[1]<=out[0];
out[0]<=in[0];
end
endmodule
module Mux4Bit8To1(input[3:0] in0, input[3:0] in1, input[3:0] in2, input[3:0] in3, input[3:0] in4, input[3:0] in5, input[3:0] in6, input[3:0] in7, input[2:0] selector, output reg[3:0] out);
assign S0 = selector[0];
assign S1 = selector[1];
assign S2 = selector[2];
assign out = S2 ? (S[1] ? (S[0] ? in7 : in6) : (S[0] ? in5 : in4)) : (S[1] ? (S[0] ? in3 : in2) : (S[0] ? in1 : in0))
endmodule
module RegisterFile(input clock, input clear, input[3:0] write_data, input[2:0] write_index, input write, input[2:0] read_index, output[3:0] read_data);
reg[7:0] content[3:0]; //this line is initializing the register
integer i;
always #(posedge clear, negedge clock). //this is the senstivity list of the always block
if (clear) begin
for (i = 0; i < 4; i = i + 1)
content[i] = 0; //this line is clearing out all the memory locations
end else if (write)
content[write_index] = write_data. //this line is performing a write operation
else
endmodule
Verilog describes hardware. As a result the final product is set of connected elements. In your case you need to instantiate and connect your modules.
In verilog it looks like the following:
module in(input clk, input data, output reg value);
always #(posedge clk)
value <= data;
endmodule
The above module has clock, input data and output value;
module out(input clk, input value, output reg data);
always #(posedge clk)
data <= ~value;
endmodule
And finally you need to assemble them:
module device(input clk, input datain, output dataout);
wire val;
in in(clk, datain, val);
out out(clk, val, dataout);
endmodule
in the device, two modules are instantiated. The val plays a role of a connecting wire which connects output of module in with input of module out.
So, you can extend this scheme to your model.
I have below code inside SV module where I instantiate another SV module and pass 5-bit bus to it to check for X and Z's as coded below:
input [4:0] analdo_trim;
cds_XZ_checker XZ_check_analdo_trim (.in(analdo_trim),.in_ok(analdo_trim_ok));
Here is module definition for cds_XZ_checker:
module cds_XZ_checker(in,in_ok);
input in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule
The issue is when I read 5-bit analdo_trim in above module via in port, it only reads LSB of analdo_trim because it doesn't have bus width in declaration.
Module cds_XZ_checker is generic module which is instantiated inside several other modules. Hence, I can't declare 'in' as [4:0] as some other modules might pass bus with different bit width. Is there a way I can parameterize this so that it will work for any bit width?
You can use a parameter to accommodate different input bus widths:
module cds_XZ_checker #(parameter WIDTH=5) (in,in_ok);
input [WIDTH-1:0] in;
output bit in_ok;
always_comb begin //Asynchronous assertion check block
asynch_XZ_check: assert (!($isunknown(in))) in_ok=1'b1;
else begin
$warning ("WARNING (%M) digital signal in=%b is undefined at time %t",in,$time);
in_ok=1'b0;
end//else
end
endmodule
module tb;
logic a,b;
logic [4:0] c;
logic d;
cds_XZ_checker #(.WIDTH(1)) i0 (a, b);
cds_XZ_checker i1 (c, d);
endmodule
The tb module shows how you would parameterize each instance of the checker module. The default width is 5. If your checker input is 5-bit, then passing the parameter is optional.
Demo on edaplayground
I'm trying to create a Verilog wrapper for a VS counter.
I have written the following SystemVerilog code for the counter:
//counter.sv
interface counter_if(input clk, rstn);
logic [3:0] out;
modport dut(input clk,rstn, output out);
endinterface : counter_if
module counter(counter_if.dut cnt);
always # (posedge cnt.clk) begin
if (! cnt.rstn)
cnt.out <= 0;
else
cnt.out <= cnt.out + 1;
end
endmodule
Also, I've written the following Verilog code:
//wrapper file
module counter_wrapper(clk,rstn,out);
input clk;
input rstn;
output reg [3:0] out;
counter_if cnt (.clk(clk), .rstn(rstn));
counter cnt0 (
.cnt(cnt)
);
endmodule
When I compile it, I get the following error for the Verilog file:
Error: (vlog-2110) Illegal reference to interface "cnt"
So I changed the interface call to the following:
//wrapper file
module counter_wrapper(clk,rstn,out);
input clk;
input rstn;
output reg [3:0] out;
counter_if cnt (.clk(clk), .rstn(rstn));
counter cnt0 (
.cnt(cnt.dut)
);
endmodule
Now the design compiles, but when simulating the following error comes up:
Error: (vsim-3044) Usage of 'cnt.dut' inconsistent with 'modport' object.
Any insight will be highly appreciated!
Standard-compliant Verilog code cannot instantiate a SystemVerilog interface. You'll need to either use an SV wrapper or remove the interface and replace it with normal module ports. Verilog can connect to SV just fine (in most tools) with regular module ports.
//counter.sv
module counter (
input logic clk,
input logic rstn,
output logic [3:0] out
);
always # (posedge clk) begin
if (!rstn)
out <= 0;
else
out <= out + 1;
end
endmodule
This is not about actually creating a verilog module with inout ports. There are tons of posts I've found about that.
What I am stuck on is, if I have a blackbox module with an inout port, let's says it's defined like
module blackbox(inout a, in b, in c)
And I want to instantiate it in a different module like
module myModule(input reg inReg, output wire outWire)
blackbox(outWire);
How do I also drive the blackbox with the inReg and have it output on the outWire at different times? I don't know of a way to connect one and disconnect the other. This is obviously oversimplified. What I really have is below, but it's more complicated.
module sram_control(
input wire HCLK,
input wire [20:0] HADDR,
input wire HWRITE,
input wire [1:0] HTRANS,
input wire [7:0] HWDATA,
output reg [7:0] HRDATA
);
parameter IDLE_PHASE = 2'b00;
parameter WRITE_PHASE = 2'b01;
parameter READ_PHASE = 2'b10;
parameter IDLE = 2'b00;
parameter NONSEQ = 2'b10;
parameter READ = 1'b0;
parameter WRITE = 1'b1;
reg current_state, next_state;
wire CE, WE, OE;
reg [20:0] A;
wire [7:0] DQ;
reg [7:0] DQ_tmp1;
wire [7:0] DQ_tmp2;
async the_mem(.CE_b(CE), .WE_b(WE), .OE_b(OE), .A(A), .DQ(DQ));
always #(posedge HCLK) begin
if(current_state == IDLE_PHASE) begin
next_state <= HTRANS == NONSEQ? (HWRITE == WRITE? WRITE_PHASE : READ_PHASE) : IDLE_PHASE;
A <= HADDR;
end
else if(current_state != IDLE_PHASE) begin
if(HTRANS == NONSEQ) begin
if(HWRITE == WRITE) begin
next_state <= WRITE_PHASE;
end
else begin
next_state <= READ_PHASE;
end
end
else next_state <= IDLE_PHASE;
end
// we never get here
else next_state <= IDLE_PHASE;
end
always#(posedge HCLK) begin
if(current_state == READ_PHASE) HRDATA <= DQ;
end
assign CE = current_state != IDLE_PHASE? 1 : 0;
assign WE = current_state != IDLE && HWRITE == WRITE? 1 : 0;
assign OE = current_state != IDLE_PHASE? 1 : 0;
always#(posedge HCLK) current_state <= next_state;
endmodule
What I need is a way to assign HWDATA to the async module when I want to write to it, and I need a way to assign the output of the async module to HRDATA when I want to read from the async.
For all inout ports, you can read the data at any time. But for driving that net, generally tri state buffers are used. The reason for that is the same net may be shared with multiple modules and since the net is on inout type, to remove conflict of multiple driver, the tri state buffers are used.
For the same above image, here is the code.
assign io = t ? i : 1'bz; // To drive the inout net
assign o = io; // To read from inout net
As you say, this isn't a Verilog question, it's a logic design question.
You need to implement a tri-state driver to drive DQ:
assign DQ = WE ? 8'bz : HWDATA;
(assuming WE is 1'b0 when you are doing a write).
In general I would avoid tri-state logic inside an IC/FPGA, because not only is there the obvious problem when more than one driver drives a bus, it is also a problem if nothing drives the bus (some gates get floating inputs). There are also further problems in IC design. However, presumably you have not choice in this case; presumably you did not design module async. (If you did - take out the inout.)
I am new to verilog and I am writing a code in verilog for creating a memory block capable to read and write data. it has the following code
I tried all things written in some of the answers of similar type of questions but still I am getting an error.
module memory( wr_n , rst_n ,data ,clk ,add , en);
input wire wr_n;
input wire rst_n;
input wire clk;
input wire en;
parameter size = 255;
parameter n = 7;
inout wire [n:0] data;
input wire [n:0] add;
reg [n:0] mem [size:0];
integer i;
always #( posedge clk , negedge rst_n)
begin
if(!rst_n)
begin
for( i=0; i<=size; i=i+1 )
begin
mem[i] <= 8'hff;
end
end
else
begin
if(en)
begin
if(!wr_n) //read
data <= mem[add];
else //write
mem[add] <= data;
end
else
data = 8'h z;
end
end
endmodule
here when I use continuous assignment before data I get an error like
"LHS in procedural assignment may not be a net:data"
even if I have declared it as wire.
and yeah in my test bench I have declared data as reg type because when I declare it as net it shows again the
"Illegal reference to net error".
I am not able to fix it since long time..please help me out.
The inout port 'data' is of type wire. So, it cannot be used on the left hand side of the <= expression in a procedural block (always block and initial block).
So we should use continuous assignment statements like
assign data = (wr_n == 0)? mem[add]:n{1'bz};
The same holds true when we are driving any values on the inout port form the test bench. The signal connecting to the inout port from the test bench must be of type wire. And hence it should also be written using continuous assignment statements.
assign testbench_inout_signal = (wr_n == 0)? value_to_be_written :n{1'bz};
There is a better way of using an inout port, it should be isolated from the logic to avoid conflicts while reading and writing, remember whenever you use inout ports make sure the points mentioned in the link are satisfied.
One such solution is declare a temporary variable for reading and writing and
by using continuous assignment statement assign values to bidirectional port.
Following snippet will give you some more clearance of how the error can be avoided
reg [n:0] temp; // declare a variable and try to read and write with this variable
if(!wr_n) //read
temp <= mem[add];
else //write
mem[add] <= temp;
assign data = (wr_n==0)? temp : {n{1'bz}};
Remove the else part having data = 8'h z; there cannot be two else for single if statement as per LRM.