Author Topic: [newbie] Doubt on verilog code  (Read 877 times)

0 Members and 1 Guest are viewing this topic.

Offline greenstrikeTopic starter

  • Contributor
  • Posts: 17
  • Country: it
[newbie] Doubt on verilog code
« on: May 30, 2023, 04:15:40 pm »
Hi guys, I'm starting using verilog.
I need Numerically Controlled Oscillator as clock generator but code I've found on the web is too complicated for me, so I'm designing my NCO step by step.
I am using overflow bit as flag, to be cleared after 1 clock cycle.


Here my working (until now) code:

Code: [Select]
module NCO_4bit
#(
parameter WACCUM = 24 // accumulator register width [bits]

/*
output frequency [MHz] = (step [counts] * Fosc [MHz])/(2^WACCUM)
example:

always #5 ck = ~ck; clock period = 10ns, clock frequency = 100 [MHz]
WACCUM = 8 [bits]
step = 3 [value]
output frequency fout = 1.1764705882 [MHz]
*/
)
(
input [WACCUM-1:0] step, // phase value
output reg [WACCUM:0] accu, // accumulator
output fout, // output frequency
input n_res, // clear command (active low)
input ck // system clock (on rising edge)
);



wire [WACCUM:0] mask;
assign mask =   {       {1'b0},             {(WACCUM){1'b1}}      }; // creating mask, WACCUM+1 bits wide, only MSB 0, remaining bits set to 1


// check for reset, check at falling edge of n_res or every rising edge of ck
always @(posedge ck or negedge n_res)
begin


if (!n_res)
accu <= 0; // clear accu register
else
   begin
// check if accu MSB is set, if so clear it so fout high only for 1 clock cycle
//$display("\ninit accu= %b, flag= %b", accu, accu[WACCUM]);
if (accu[WACCUM])
     begin
    //accu[WACCUM] <= 1'b0;
accu <= (accu+step)&mask;
   end
else
   begin
accu <= accu+step;
   end
$display("current accu value= %b, flag= %b", accu, accu[WACCUM]);
   end
end

assign fout={accu[WACCUM]};

endmodule

It looks working, I just add "step" value to "accu" and using MSB of accu register to detect rollover of the counter.
I want rollover flag (fout) high for 1 clock cycle, then I clear it.

First code I wrote:
Code: [Select]
if (!n_res)
accu <= 0; // clear accu register
else
   begin
// check if accu MSB is set, if so clear it so fout high only for 1 clock cycle
//$display("\ninit accu= %b, flag= %b", accu, accu[WACCUM]);
if (accu[WACCUM])
     begin
    accu[WACCUM] <= 1'b0;
   end
accu <= accu+step;
   end


When detecting MSB set I try to clear it, but no effect.
I also tested accu <= 5 as test.
I can enter inside if (accu[WACCUM]) but it looks

accu <= accu+step;

would override all previous instructions.
Am I missing something?
Thanks.
 

Online langwadt

  • Super Contributor
  • ***
  • Posts: 4803
  • Country: dk
Re: [newbie] Doubt on verilog code
« Reply #1 on: May 30, 2023, 07:04:00 pm »
the last assignment "wins" so you need to have the default "accu <= accu+step;" first 


you could do it all in one line

reg fout;

{fout,accu} <= {1'b0,accu}+{1'b0,step};
 

Offline greenstrikeTopic starter

  • Contributor
  • Posts: 17
  • Country: it
Re: [newbie] Doubt on verilog code
« Reply #2 on: May 31, 2023, 12:27:17 pm »
Ok, thanks, finally  I've understood difference between blocking and non-blocking...
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf