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.

Clock divider (soon to be with enable and single step).

Status
Not open for further replies.

Mark Baseggio

Junior Member level 2
Junior Member level 2
Joined
Nov 2, 2013
Messages
22
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
249
Hello,

I am working on building a homebrew computer, when learned about bus decoding I decided that it would be awesome to learn PLD in the process. And so here I am. I've got the Dangerous Prototypes CPLD breakout, and the Mojo v3 from Embedded Micro (with a Spartan 6). Currently I'm prototyping with it because it has a 50Mhz clock on the board and the CPLD doesn't.

After some Googling and searching on this forum I have a basic 1Mhz clock divider working, or so it appears according to my Saleae Logic probe. This small feat has me excited for the opportunities and plans I have for this computer.

I was hoping that a few people could take a gander at my clock divider code and provide some feedback, because I'm not sure if I'm doing it the best or "proper" way. Also, as the topic says I plan on integrating a few buttons: one to stop the clock (note it must be stopped HIGH to prevent memory loss on the 6502), and another to then single step the CPU one clock cycle at a time (always stopping high for reasons already mentioned).

If anyone feels like providing suggestions I'd be grateful! Here's the code:

Code:
module clock_div(
    input clk,
	 input rst,
	 output mpu_clk
	 );

parameter period = 50;
parameter halfperiod = 25;

reg mpu_clk;
wire rst,clk;
reg [5:0] countvalue;

always @(posedge clk) begin
  if(rst) begin
    countvalue <= 5'b0;
    mpu_clk <= 1'b0;
    end
  else begin
    if(countvalue == period - 1'b1) begin
      countvalue <= 1'b0;
      mpu_clk <= 1'b0;
      end
    else countvalue <= countvalue + 1'b1;
    if(countvalue == halfperiod) mpu_clk <= 1'b1;
    end
end
  
endmodule

in my constraints file I also had to add the following:

Code:
NET "mpu_clk" LOC = P1;

And the result, YAY it works (I know, this is simple stuff, but give me a break, baby steps here!)

1mhz.png

Oh and one last thing. Eventually I will also be needing a 20Mhz clock to communicate with a SPI SRAM that I will be adding. Would it be advisable to generate both signals in the same module?

Thanks for reading!
 
Last edited:

Code looks pretty good, especially if you're just starting out. :)

One thing though, don't get into the habit of using this style of division to generate clocks. You're better of using the PLL (since you said you're using spartan-6 right now).

If you use division like you just did, you'll get a "clock" that is routed across the fpga with generic (aka bleeding high skew) routing resources. The PLL output on the other hand will be routed using a global clock net, which gives you nice low skew. Which means it's easier for your design to meet timings at high frequency.

So nothing wrong with the above, as long as you're aware that you had better limit that sort of divider to low clock frequencies.

Incidentally, it's easier to just have a counter that counts up to halfperiod and then toggles the mpu_clk reg.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
always @(posedge clk) begin // the lack of rst in this sensitivity list implies that it's a synchronous reset
  if(rst) begin
    countvalue <= 5'b0;
    mpu_clk <= 1'b0;
    end
  else begin
    if(countvalue == halfperiod - 1'b1) begin
      countvalue <= 1'b0;
      mpu_clk <= ~mpu_clk; // toggle mpu clock signal
      end
    else countvalue <= countvalue + 1'b1;
    end
end



- - - Updated - - -

Oh and one last thing. Eventually I will also be needing a 20Mhz clock to communicate with a SPI SRAM that I will be adding. Would it be advisable to generate both signals in the same module?

I usually instantiate a clocks_and_resets module in my top level. That clocks_and_resets thing then contains all the PLL cores, clock buffers if needed, reset synchronizers ... that sort of thing. So I'd say make one module per clock source, and then instantiate all those inside a module dedicated to clocking.
 
Thanks for your quick and helpful reply! I just noticed that I am getting a few warnings related to this module when I generate the programming file:

Code:
Line 16: Redeclaration of ansi port mpu_clk is not allowed
Line 17: Redeclaration of ansi port rst is not allowed
Should I be declaring them as reg and wire up in the module section?

One other warning I don't understand:

Code:
FF/Latch <mpu_clock_divider/countvalue_5> has a constant value of 0 in block <mojo_top>. This FF/Latch will be trimmed during the optimization process.

it looks like this is optimizing away the counter that I use, but inexplicably the routine still works. So it must not be. I am scratching my head. :)

Also, I noticed that you added the comment "// the lack of rst in this sensitivity list implies that it's a synchronous reset" Can you please explain that one to me a bit more, I'm not 100% sure what you mean. I assume that because I am not passing the rst value to sensitivity that rst won't ever be true so that code block will never work.. but somehow I think I am wrong.

Thanks again.

Thanks!
 
Last edited:

Thanks for your quick and helpful reply! I just noticed that I am getting a few warnings related to this module when I generate the programming file:

Code:
Line 16: Redeclaration of ansi port mpu_clk is not allowed
Line 17: Redeclaration of ansi port rst is not allowed
Should I be declaring them as reg and wire up in the module section?

Yup. Declaring them in the port declaration (up in the module section) is a clean way to do it. And the "wire" part is optional (in the port declaration), since wire is the default nettype. So you can explicitely use "wire" and it will work, and you can omit it, and it will also work fine.

One other warning I don't understand:

Code:
FF/Latch <mpu_clock_divider/countvalue_5> has a constant value of 0 in block <mojo_top>. This FF/Latch will be trimmed during the optimization process.

it looks like this is optimizing away the counter that I use, but inexplicably the routine still works. So it must not be. I am scratching my head. :)

If you're using my suggested code, it now counts only up to halfcount-1 which is 24. That fits nicely in countvalue[4:0], so countvalue[5] is always 0. And as such it's being optimized away.

Also, I noticed that you added the comment "// the lack of rst in this sensitivity list implies that it's a synchronous reset" Can you please explain that one to me a bit more, I'm not 100% sure what you mean. I assume that because I am not passing the rst value to sensitivity that rst won't ever be true so that code block will never work.. but somehow I think I am wrong.

Your code will work. What you described there is synchronous logic with a synchronous reset.

MmMmh, it's a bit much to describe properly. This paper has a good explanation of what I mean, and more: http://www.sunburst-design.com/papers/CummingsSNUG2003Boston_Resets.pdf

Short version: what you want for fpga is sync or async assert (whichever is convenient) and always SYNC deassert of reset. Anyways, lotsa info in that paper.
 
Ohhh, ahahah. I did change the code so it's very similar to yours. It didn't occur to me that I now only need 5 bits, duuhh thanks!

Also, I fixed the declarations - thanks for the clarification. Looks like I will be able to get rid of all of those warnings. Now to figure out how to add the enable and single step features...

After that I will be interfacing the 6502 data and address busses to the FPGA so I can have some more fun. I appreciate the PDF link, I will be checking it out for sure.
 
Last edited:

Just changed the code a little bit to add a switch to stop the clock (high) as mentioned previously:

Code:
always @(posedge clk) begin
  if(rst) begin
    countvalue <= 5'b0;
    mpu_clk <= 1'b0;
    end
  else begin
    if(countvalue == PERIOD - 1'b1) begin
      countvalue <= 1'b0;
      mpu_clk <= ~mpu_clk; // toggle mpu clock signal
      end
	 if (!clk_switch && mpu_clk) begin
	 //clock stopes high if the clk_switch is low. 
	 end
    else countvalue <= countvalue + 1'b1;
    end
end

Seems to be working well, aside from the obvious need for debouncing... time to figure out how to debounce a switch I guess. I am using this tutorial from Mojo seems like it shouldn't be that hard to put in to my code. Right now I'm just trying to figure out if I can use the same module for different buttons...

Here's a screenshot without the debounce:

1mhz-hold-nodebounce.png
 

Right now I'm just trying to figure out if I can use the same module for different buttons...

That's the idea. You make one generic module that can take care of debouncing, and then you instantiate it for each of the buttons.


Oh and ...

Code Verilog - [expand]
1
countvalue <= 1'b0; // you probably mean 5'b00000 here or 5'd0. But right now you are using a 1-bit wide value...



As for button debounce, you can sample the input at a relatively low frequency and put it into a shift register. Then you bit-reduce AND / OR them based on last state. As in suppose last state was 0, then you want the shift register to contain all ones and then you change state to 1 (aka button is pressed). When last state was 1 (button being pressed) then you want the shift register to contain all zeros before you change state back to 0 (aka button not pressed).

Actually the code for this is less characters than what I just wrote, but this way you can code it yourself. ;)

Also, since the clock used for sampling the button inputs isn't that critical you can use any reasonable slow clock you already happen to have.

Just create 1 slow clock, and then use that for all your button debouncing modules.
 
Last edited:
Alright, I'm throwing in the towel here. I implemented a straightforward debounce module that I found on the Internet:

Code:
module debounce(
	input clk,
   input PB,  // "PB" is the glitchy, asynchronous to clk, active low push-button signal
   // from which we make three outputs, all synchronous to the clock
   output reg PB_state,  // 1 as long as the push-button is active (down)
   output PB_down,  // 1 for one clock cycle when the push-button goes down (i.e. just pushed)
   output PB_up   // 1 for one clock cycle when the push-button goes up (i.e. just released)
	);

// First use two flip-flops to synchronize the PB signal the "clk" clock domain
reg PB_sync_0;  always @(posedge clk) PB_sync_0 <= ~PB;  // invert PB to make PB_sync_0 active high
reg PB_sync_1;  always @(posedge clk) PB_sync_1 <= PB_sync_0;

// Next declare a 16-bits counter
reg [15:0] PB_cnt;

// When the push-button is pushed or released, we increment the counter
// The counter has to be maxed out before we decide that the push-button state has changed

wire PB_idle = (PB_state==PB_sync_1);
wire PB_cnt_max = &PB_cnt;	// true when all bits of PB_cnt are 1's

always @(posedge clk)
if(PB_idle)
    PB_cnt <= 0;  // nothing's going on
else
begin
    PB_cnt <= PB_cnt + 16'd1;  // something's going on, increment the counter
    if(PB_cnt_max) PB_state <= ~PB_state;  // if the counter is maxed out, PB changed!
end

assign PB_down = ~PB_idle & PB_cnt_max & ~PB_state;
assign PB_up   = ~PB_idle & PB_cnt_max &  PB_state;

endmodule

It works great, except for one thing -- it's throwing my clock off :( Now I'm getting an alternating 800khz/775khz clock for some reason. I suspect this must have something to do with blocking assignments, but I can't figure out what to do about it. Just in case, here is my current clock module as well:

Code:
module mpu_clock_div(
    input clk,
	 input rst,
	 input clk_en,
	 input step_press,
	 output reg mpu_clk
	 );

localparam PERIOD = 24; // 1Mhz with 50% duty cycle.

reg [4:0] countvalue = 5'b0; 

always @(posedge clk) begin
  if(rst) begin
    countvalue <= 5'b0;
    mpu_clk <= 1'b0;
    end
  else begin
    if(countvalue == PERIOD) begin
      countvalue <= 5'b0;	// reset counter 
      mpu_clk <= ~mpu_clk; // toggle mpu clock signal
      end
    if (clk_en && mpu_clk) begin
	//clock stops high when clk_en is true. 
      end
    else countvalue <= countvalue + 5'b1;
    end
end
  
endmodule

When I remove the debounce it seems to work perfectly. Sooo. I'm not sure what the heck is going on. It's probably something really simple, that my noobness isn't able to catch :) Once again, thanks sooo much for all the help here!

I will be doing a youtube video once I get the basic clock functionality working to document the project from start to finish, I'll be sure to post it when it's up!

I put the entire source tree on github: https://github.com/blark/6502_verilog_src
 
Last edited:

Normally I would expect a debounce block to have no effect on the clock source. As in, debounce is a consumer of the clock signal, not a producer, not does it have any influence on it. If it does, then something fishy is going on.

How did you test if it was working or not? In hardware or with a testbench? If testbench, please post it + screenshot of the simulation result. If you didn't testbench it ==> then testbench it. ;)

Let me guess, you grabbed that debounce like that from the internet. Because it looks horribly overcomplicated and unreadable for something that's supposed to do just a debounce. It reads a bit like someone is used to using counters for debouncing on a mcu, and then decided to translate that habit to fpga.

All you really need is a shift-register + a case statement that does a bit-reduce AND for one state, and a bit-reduce OR for the other state. The bit-reduce and/or basically checks if it is all ones/zeros respectively.

For reduction operators, see: https://www.asic-world.com/verilog/operators2.html
 

Yeah, I think I got that from fpga4fun.com. I tested it in hardware, wrote it to the Mojo dev board and used my Saleae logic to test afterward..

I'll look at some other routines and see if I can put what you're describing in to code. Thanks
 

Lol. Turns out I'm just thick. If you look back to the source of my clock you'll see that I used "if (clk_en && mpu_clk) begin" rather than "else if..." Took me a while to hunt down that stupid bug. But now it seems to be working great, even with single stepping.

I tried to use a shift register to do debouncing, but the issue I found is that the register was filling up way too fast. So I generated a slower clock signal, and it worked well. At that point I realized I would need to alter the debounce routine so it also sent a second output that is high for 1 50mhz clock so I my clock routine could single step. The thought of frigging around with my own debounce and adding that functionality versus using what I had already found... well let's just say I used the debounce that already had that feature :)

Is there a better approach than feeding the debounce routine a separate clock to slow down the shift register?
 

Is there a better approach than feeding the debounce routine a separate clock to slow down the shift register?

Yeah. An RC filter and a Schmitt trigger. :p

Other than that, nothing wrong with using a slow sampling clock. Oh and incidentally, now is about the time to go look into clock enables. Because you can just clock the shift register with your 50 MHz clock, and then have a counter that generates the clock enables for you. Basically the clock enable goes high for 1 cycle when the counter overflows. So if for example your counter counts from 0 to 999, then your clock enable is high 1 in 1000 cycles ==> sample rate is 50 kHz.
 
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top