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.

Multiple ring oscilators verilog code

Status
Not open for further replies.

rayaprolu

Newbie level 5
Newbie level 5
Joined
Oct 9, 2013
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
124
Hi,

I am trying to write a verilog code for a simple design of MUX and few ROs. I am very naive to verilog and hence not able to write it efficiently. Can some one help me write a synthesizable code for design attached with this post?
My code that i m trying to write is as follows but i am facing errors:
module top_tb ();

wire osc_out_tb;
reg in_tb, sel_tb;

top dut(in_tb, sel_tb, osc_out_tb);


initial begin
in_tb = 8'b00000001;
sel_tb = 3'b001;
#10 sel_tb=3'b010;
#10 sel_tb=3'b011;

end
endmodule

module top (in, sel, osc_out);

input [7:0] in;
input [2:0] sel;
wire [3:0] en;

output [3:0] osc_out ;

generic_RO u_generic_RO1( .en_G(en[0]), .osc_out_G(osc_out[0]));
generic_RO u_generic_RO2( .en_G(en[1]), .osc_out_G(osc_out[1]));
generic_RO u_generic_RO3( .en_G(en[2]), .osc_out_G(osc_out[2]));
generic_RO u_generic_RO4( .en_G(en[3]), .osc_out_G(osc_out[3]));


mux_top u_mux_top(.in (in),.sel (sel), .en_out (en) );


endmodule

module generic_RO (en_G, osc_out_G);

input en_G;
output osc_out_G;

reg [num-1:0] Ro_Out_arr;


parameter num=25;

//reg Ro_Out_AND = 1'b1;

genvar i;
generate


for(i=0; i<num; i=i+1) begin :inst


ringosc5 ringosc_n(
.Rosc_out (Ro_Out_arr),

.en (en_G)
);

// Ro_Out_AND = (Ro_Out_arr && Ro_Out_AND); //j variable will be constant for i=1 to 25.
//After 25 times of i, j increments 1 time.


end

//assign osc_out_G = Ro_Out_AND;
endgenerate

endmodule
module ringosc5 (Rosc_out, en);
input en;
output Rosc_out;
wire Rosc_out;
reg [5:1] node /* synthesis keep*/;
reg Rosc_out_reg;


always @(Rosc_out or en)
begin
node[1]<= ~(node[5] & en);
node[2]<= ~node[1];
node[3]<= ~node[2];
node[4]<= ~node[3];
node[5]<= ~node[4];

Rosc_out_reg<=node[5];

end

assign Rosc_out = Rosc_out_reg;

endmodule
module mux_top(in,sel, en_out);

input [7:0] in;
input [2:0] sel;
output [3:0] en_out;

reg [3:0] en_out;

always @ (sel or in)
begin
case(sel)
3'b000 : begin
en_out[0] = in[0];
en_out[3:1] = 3'b0;
end
3'b001 : begin
en_out[0] = in[1];
en_out[3:1] = 3'b0;
end
3'b010 : begin
en_out[1] = in[2];
en_out[3:2] = 2'b0;
en_out[0] = 1'b0;
end
3'b011 : begin
en_out [1] = in[3];
en_out[3:2] = 2'b0;
en_out[0] = 1'b0;
end
3'b100 : begin
en_out[2] = in[4];
en_out[3] = 1'b0;
en_out[1:0] = 2'b0;
end
3'b101 : begin
en_out[2] = in[5];
en_out[3] = 1'b0;
en_out[1:0] = 2'b0;
end
3'b110 : begin
en_out[3] =in[6];
en_out[2:0] = 3'b0;
end
3'b111 : begin
en_out[3] = in[7];
en_out[2:0] = 3'b0;
end
endcase
end

endmodule

- - - Updated - - -

I forgot to mention, all the individual outputs of each RO, has to be tied together and AND them to draw it out on one pin. This will prevent the compiler to optimize and throw it away.
 

Attachments

  • eb1.png
    eb1.png
    17.8 KB · Views: 101

You never mentioned what errors you are seeing.

I noticed that you didn't include the correct signals in the sensitivity list of your always. You should use Verilog 2001, which means you can write always @ (*) and then you don't have to worry about having all the RHS signals in the list. I would also just code the nodes as:
Code:
wire [5:0] node;
assign node = {~node[4:0], ~node[5] & en};

Of course you won't be able to simulate this as there is no "delay", Modelsim will probably report something about 5000 iterations and abort the simulation, but as long as all the bits of node aren't removed in synthesis it might oscillate if there is enough physical delay though the entire ring: LUT+wire delays.

If you want to model the delay so Modelsim will work. You can model the ring with.

Code:
always @(*) begin
  node <= #10 {~node[4:0], ~node[5] & en};
end
This will give you a 10 time unit transport delay between each node, and synthesis will ignore the #10.

Of course I haven't coded something like this before as it's not a good design practice in an FPGA, so it still might not simulate correctly.

Regards
 

Naive approach: implement just a single ring oscillator, without any MUX to further complicate things.

Also, please use [syntax=verilog] tags as .

As for simulating ring oscillators ... come to think of it I never actually simulated those. I alwyas just synthesized it and then verify placement and such, and then measure the output. But if you want to simulate this and get anything meaningful, you will have to do a post place & route simulation.
 

Hi,

Thank you both for the replies.

Even if i compile only a single RO as below, I get the error.

Code:
[syntax=verilog]
module tryring_tb;

reg en;
wire osc_out;
//input en;
//output osc_out;



initial begin
en = 1'b0;
#5 en = 1'b1;
end

tryring  u_tryring( .en(en), .osc_out(osc_out));

endmodule

module tryring (en, osc_out);
input en;
output osc_out;
wire osc_out_reg;

reg [4:0] node /* synthesis keep*/ ;
assign node=5'b11111;

reg osc_out_reg;


//always @(en or osc_out_reg)
always @(*)

begin
node[0]<= ~(node[4] & en);
node[1]<= ~node[0]; 
node[2]<= ~node[1];
node[3]<= ~node[2];
node[4]<= ~node[3];


osc_out_reg<=node[4];

end 

assign osc_out= osc_out_reg;
 
endmodule 


assign wire0 = ~ wire1;
assign wire1 = ~ wire2;


[/syntax]

I urgently need help on this, please help me.

Thank you so much!

- - - Updated - - -

The error that i get is :
Info (12127): Elaborating entity "tryring_tb" for the top level hierarchy
Info (12128): Elaborating entity "tryring" for hierarchy "tryring:u_tryring"
Error (12061): Can't synthesize current design -- Top partition does not contain any logic
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 1 error, 0 warnings

Error: Peak virtual memory: 478 megabytes
Error: Processing ended: Wed Oct 09 09:58:57 2013
Error: Elapsed time: 00:00:12
Error: Total CPU time (on all processors): 00:00:04
 

Your top level module is tryring_tb, looks to be just a testbench that applies stimulus, which of course has no synthesizable logic. You should use tryring as the top-level file. You also have a continuous assignment to node on line 25 that will result in an error. If you want the reg on line 24 to have an initial value of all 1's then use reg [4:0] node = 5'b11111;. You've defined osc_out_reg twice once as a wire and as a reg.

You should read a Verilog book or online tutorial. A lot of mistakes you've made are due to not knowing the syntax of the language.

Regards
 

hi ads-ee,

thank you. Yes i m already taking help of book and in parallel working on this. I thought the forum would help because its kind of an urgent task for me.
I have some Qs:
1)If i use tryring.v as top level, then can i still provide stimulas through *_tb.v file?
2)Can you help me in quickly giving me the correct code for this project (the pic attached to my 1st post, since this is a very basic one) so that i get started with a correct and proper flow of program to understand this programming better?

I understand it could be time consuming for you but would really help me :|

I will anyways make the changes as you suggested and get back.

Thanks a ton.

- - - Updated - - -

hi ,
I made the *.v file as top level and it compiles without errors. But, I dun see any stimulus going to the .v file from *_tb.v file. How can i make "en" high and initialize the "node[4]"? Only if i initialise these two, the RO will work, correct?
 

1)If i use tryring.v as top level, then can i still provide stimulas through *_tb.v file?
yes

2)Can you help me in quickly giving me the correct code for this project (the pic attached to my 1st post, since this is a very basic one) so that i get started with a correct and proper flow of program to understand this programming better?
Sorry I can't do someone's homework for them, but I'm willing to give input to help then resolve problems. And if this is for a job, then I'm open to freelance consulting work, but my rate is pretty steep. ;-)

I made the *.v file as top level and it compiles without errors. But, I dun see any stimulus going to the .v file from *_tb.v file. How can i make "en" high and initialize the "node[4]"? Only if i initialise these two, the RO will work, correct?
Do you mean you synthesized the design without errors in Quartus II or you tried to simulate the design without the *_tb file? If you're trying to run the simulator from Quartus II then you'll have to make sure the simulator uses *_tb.v file as the top level and the synthesis uses the *.v file. I've always used a stand alone Modelsim simulator and never run into this issue as I never include my testbench files in the synthesis tool.

Regards
 

hi,

Yes, I synthesized it without errors. Does it mean that i can check it on real hardware?
How about the design with MUX and many ROs?
Is it correct way of writing the code as following for the design i mentioned in my first post with MUX?
Code:
[syntax=verilog]
module top (in, sel, osc_out);

input [7:0] in;
input [2:0] sel;
wire [3:0] en;

//output [99:0] osc_out ;

output [3:0] osc_out ;

//generic_RO u_generic_RO1(.osc_out(osc_out[24:0]), .en(en[0]));
//generic_RO u_generic_RO2(.osc_out(osc_out[49:25]), .en(en[1]));
//generic_RO u_generic_RO3(.osc_out(osc_out[74:50]), .en(en[2]));
//generic_RO u_generic_RO4(.osc_out(osc_out[99:75]), .en(en[3]));

generic_RO u_generic_RO1( .en_G(en[0]), .osc_out_G(osc_out[0]));
generic_RO u_generic_RO2( .en_G(en[1]), .osc_out_G(osc_out[1]));
generic_RO u_generic_RO3( .en_G(en[2]), .osc_out_G(osc_out[2]));
generic_RO u_generic_RO4( .en_G(en[3]), .osc_out_G(osc_out[3]));


mux_top u_mux_top(.in (in),.sel (sel), .en_out (en) );
						 			
									
endmodule								

module mux_top(in,sel, en_out);

input [7:0] in;
input [2:0]  sel;
output [3:0] en_out;

reg [3:0] en_out;

always @ (sel or in)
begin 
 case(sel) 
    3'b000 : begin 
	 en_out[0] = in[0];
    				 en_out[3:1] = 3'b0;
					 end
    3'b001 : begin
				 en_out[0] = in[1];
             en_out[3:1] = 3'b0;
				 end
     3'b010 : begin
	              en_out[1] = in[2];
     				  en_out[3:2] = 2'b0;
     				  en_out[0] = 1'b0;
					  end
      3'b011 : begin
		en_out [1] = in[3];
     					 en_out[3:2] = 2'b0;
     				   en_out[0] = 1'b0;
     				   end
       3'b100 : begin
		 en_out[2] = in[4];
      					en_out[3] = 1'b0;
     				   	en_out[1:0] = 2'b0;
							end
        3'b101 : begin
		  en_out[2] = in[5];
        				en_out[3] = 1'b0;
     				   		en_out[1:0] = 2'b0;
								end
         3'b110 : begin
			en_out[3] =in[6];
         				  en_out[2:0] = 3'b0;
     				   		end
          3'b111 : begin
			 en_out[3] = in[7];
          				 en_out[2:0] = 3'b0;
 end
 endcase 
end

endmodule

module generic_RO (en_G, osc_out_G);

input en_G;
output osc_out_G;

reg [num-1:0] RO_out_arr;


parameter num=25;

//reg RO_out_AND = 1'b1;
                                                                                                                        
genvar i;//,j;    
generate
	                                                                                                              
		//for (j=0; j<4; j=j+1) begin :inst1
			for(i=0; i<num; i=i+1) begin :inst
				
				
								ringosc5 ringosc_n(
								                   .Rosc_out  (RO_out_arr[i]),
														 
								                   .en       (en_G)  
														 );                                                                                           
																				
							//	RO_out_AND = (RO_out_arr[i] && RO_out_AND); //j variable will be constant for i=1 to 25. 
																					 //After 25 times of i, j increments 1 time.
									
			
	//end
				end  
	                                                                                                                          
//assign osc_out_G = RO_out_AND;
endgenerate     

endmodule

module ringosc5 (Rosc_out, en);
input en;
output Rosc_out;
wire  Rosc_out;
reg [5:1] node /* synthesis keep*/;
reg Rosc_out_reg;


always @(Rosc_out or en)
begin
node[1]<= ~(node[5] & en); 
node[2]<= ~node[1];
node[3]<= ~node[2];
node[4]<= ~node[3];
node[5]<= ~node[4];

Rosc_out_reg<=node[5];

end 

assign Rosc_out = Rosc_out_reg;
 
endmodule
[/syntax]
 

You need to define the parameter before the RD_out_arr declaration...I'm surprised it compiles.

Personally I like to use Verilog 2001 C-style port declarations on my modules, it's less repetitive with having the port name in both a wire/reg declaration and as input/output/inout. If you decide to change it also include the #( parameter num = 25) between the module name and the ports. Then you can change the num value where it's instantiated without resorting to defparam statements.

You have this always @(Rosc_out or en) instead of this always @(*). Rosc_out isn't even on the RHS and node which is, isn't included in the sensitivity list.
 

I still refer you to plan A. Kick the MUX and do a simple ring oscillator. Why? Because I doubt you'll get a ring oscillator with your current design. The typical approach is to make a string of inverters (odd amount). Since you have registers in there, chances are you'll get flip-flops. And the only way those FFs in your ring osc path are going to form an actual oscillator, is if they are latches. And latches are double bad.

I suggest you instantiate a bunch of inverters. And in terms of actual hardware, what you want is a LUT configured as inverter. And then a whole bunch of those (5 for example), cleverly spread across the fpga die so you get proper routing delays that in turn will determine the ring osc frequency.

After Place & Route you inspect the placement of those LUTs using either fpga editor or planahead. And then when you have THAT working you start faffing about with the mux, not before. Or you can take the current approach, and spend more time before you have a working solution. Your call. :p
 

Like I mentioned in post #2 rayaprolu should have used an assign.

Better yet, as mrfibble suggests rayaprolu should create a separate inverter module with all the synthesis attributes to ensure each inverter doesn't get removed in synthesis and instantiate that into a parameterized ring_oc module, so you can change the amount of delay. I would also add location constraints to your SDF/UCF that locate the every other inverter on the opposite sides of the die. I would probably build that by itself and then export it as a fully routed partition.

Regards
 

In principle assigns could work. They do have an IMO annoying drawback though. Since you declare those nodes as wires, and then use assigns to infer logic, you cannot easily apply constraints to them. If you infer LUTs however, you can directly put your constraints in your HDL. As opposed to a seperate SDF/UCF file.

Personally I like to have constraints that are very much part of the functional design in the corresponding verilog (or vhdl) file. And not in some random other file. Makes thing a lot more readable and easier to maintain IMO.

Actually, that is the one thing that would speak in favor of the registers (FFs) because you can easily constrain those from your hdl source file as well.

And for those using VHDL it's even neater, since you can generate nice constraints in a generate loop for your multiple instances. Too bad verilog suuuucks in that regard...
 

And for those using VHDL it's even neater, since you can generate nice constraints in a generate loop for your multiple instances. Too bad verilog suuuucks in that regard...

Yeah Verilog might **** at that but I'd rather use it since I don't have to type as much code. Maybe they'll add that feature to SV and then we can wait 5 years before simulators start supporting it. ;-)
 

Yeah Verilog might **** at that but I'd rather use it since I don't have to type as much code. Maybe they'll add that feature to SV and then we can wait 5 years before simulators start supporting it. ;-)

It's those pesky synthesis tools that don't support it. That's the annoying bit. If you can get it to place & route according to those constraints, then post PAR simulation is nyet problemski.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top