I believe "decompile the original rtl in file" is the conversion of RTL coding to gate-level modeling. The RTL style has always
blocks and assign
statements, while gate-level modeling only contains calls to other modules and/or standard cells. Both are functional equivalent (when written correctly). Big difference is RTL is higher level of abstraction and therefore easier to code (especially complex designs), while gate-level modeling is closer to what the silicon design will actually be and can even simulate with annotated timing.
The library file contains the definitions of all the available standard cells for a particular technology and is used for RTL to gate level conversion. In other words it is the cells that the synthesizer is allowed to use for conversion. Typically it is hold definitions for nand, nor, xor, flop-flop, buffer, inverter, etc. and various flavors of each to support timing, load, size requirements. It usually provided by a vendor or foundry.
If you do not have Verilog library, but you do have a schematic. Then find out how to export the library as Verilog. Otherwise is it possible to make a fake library by hand (just realize you cannot use it with a real project). Example: fake_udp.v
`celldefine
module FAKELIB_NAND2(output OUT, input IN0,IN1 );
assign OUT = ~(IN0 & IN1);
endmodule
module FAKELIB_NAND4(output OUT, input IN0,IN1,IN2,IN3 );
assign OUT = ~(IN0 & IN1 & IN2 & IN3);
endmodule
module FAKELIB_NOR2(output OUT, input IN0,IN1 );
assign OUT = ~(IN1 | IN0);
endmodule
module FAKELIB_INV(output OUT, input IN );
assign OUT = ~IN;
endmodule
module FAKELIB_BUF(output OUT, input IN );
assign OUT = IN;
endmodule
module FAKELIB_BUF_BIGLOAD(output OUT, input IN );
assign OUT = IN;
endmodule
module FAKELIB_DFF(output reg Q, input CLK, RST_N, SET_N, D );
FAKELIB_DFF_PRIMITIVE dff(Q, CLK, RST_N, SET_N, D);
endmodule
// ... more standard cells ...
`endcelldefine
primitive FAKELIB_DFF_PRIMITIVE(output reg Q, input CLK, RST_N, SET_N, D );
table
// CLK RST_N SET_N D : Q(state) : Q(next)
? 0 ? ? : ? : 0;
? 1 0 ? : ? : 1;
p 1 1 0 : ? : 0;
p 1 1 1 : ? : 1;
(?0) 1 1 ? : ? : -;
? 1 1 * : ? : -;
endtable
endprimitive
// ... more standard cells ...
Now Assume you have the following RTL:
module my_module(input clk, rst_n, input [2:0] in, output reg [2:0] out);
always @(posedge clk, negedge rst_n) begin
if ( !rst_n ) begin
out <= 3'b0;
end
else begin
out[0] <= ~(in[0] & in[2]);
out[1] <= ∈
out[2] <= in[1] | in[2];
end
end
endmodule
Synthesizing with the fake_udp.v as your library will give something like this: (Note: Output depends on tool and options. Also this example was done by hand)
module my_module(input clk, rst_n, input [2:0] in, output [2:0] out);
supply0 SUPVSS;
supply1 SUPVDD;
wire syn_0, syn_1, syn_2, syn_3, syn_4;
FAKELIB_NAND2 U0 (.OUT(syn_0), .IN0(in[0]), .IN1(in[2]));
FAKELIB_NAND4 U1 (.OUT(syn_1), .IN0(in[0]), .IN1(in[1]), .IN2(in[2]), .IN3(SUPVDD));
FAKELIB_NOR2 U2 (.OUT(syn_2), .IN0(in[1]), .IN1(in[2]));
FAKELIB_INV U3 (.OUT(syn_3), .IN(syn_1));
FAKELIB_INV U4 (.OUT(syn_4), .IN(syn_2));
FAKELIB_DFF out_0__reg (.Q(out[0]), .CLK(clk), .RST_N(rst_n), .SET_N(SUPVDD), .D(syn_0));
FAKELIB_DFF out_1__reg (.Q(out[1]), .CLK(clk), .RST_N(rst_n), .SET_N(SUPVDD), .D(syn_3));
FAKELIB_DFF out_2__reg (.Q(out[2]), .CLK(clk), .RST_N(rst_n), .SET_N(SUPVDD), .D(syn_4));
endmodule
I am not sure why you need a special option, the use of memories are pretty standard for use inside modules. Unless you are trying to imply a special low area/power cell similar to a ram.
For a standard memory it is just the same as having multiple regs. memory does not imply RAM the same way reg does not automatically imply flip-flop.
The 'memory.list' is a plain text file which contains the values which you want to load in to the memory, this is not required if you just wanted to reset the memory and have every element at 0.
memory.list should look like :
//Comments are allowed
1100_1100 // This is first address i.e 8'h00
1010_1010 // This is second address i.e 8'h01
@ 55 // Jump to new address 8'h55
0101_1010 // This is address 8'h55
0110_1001 // This is address 8'h56
The use of the file would then follow :
module memory();
reg [7:0] my_memory [0:255];
initial begin
$readmemh("memory.list", my_memory);
end
endmodule
alternatively :
module memory();
reg [7:0] my_memory [0:255];
integer i;
initial begin
for( i=0; i<256; i=i+1) //Can be statically unrolled
my_memory[i] = 8'h00 ;
end
endmodule
If using as a bank of flip-flops with async-reset:
module memory(
input clk,
input rst_n,
input [7:0] addr_wr,
input [7:0] data_wr
);
reg [7:0] my_memory [0:255];
integer i;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
for( i=0; i<256; i=i+1) //Can be statically unrolled
my_memory[i] <= 8'h00 ;
end
else begin
my_memory[addr_wr] <= data_wr ;
end
end
endmodule
Best Answer
After studying further i found that -c option can be used even for two files i.e. testbench.v and verilog.v.
we just need to create a ".txt" file with the name of the both the files written line after line like this
testbench.v verilog.v
and pass it to iverilog.Further i wasn't able to get any test case with the usability of -s flag, though i tried to use it in followoing case but it gives no result and give wrong .vvp file which after executing produce no .vcd file.
i used -s option with half_adder and as well as with ripple_adder_4bit but in both cases it didn't worked out.Still figuring out their use.
For reference i had used this link