GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 20 hours ago, reddish said: It should go through that little train of outputs once every 100 ns . Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 13 minutes ago, GalD101 said: 100ns? I'm not sure what is it in terms of clock cycles No, I'm asking about the period in clock cycles. That's independent of the frequency of the clock; you should be able to figure that out without knowing the clock frequency, just by inspecting the FSM module's code. This is really a question you should be able to answer. The thing goes through a bunch of states (where the state is the collection of its registered values), periodically. I want to know the period of that little dance, expressed in clock cycles. - answer it first for the 10 MHz / 30% duty cycle you did before. - then answer it for the FSM you're currently working on. It's not a problem if you don't know the answer immediately, but with a bit of thought you should be able to give those two numbers, because otherwise, you don't really understand what you're doing. It may be useful to draw a state diagram for the first FSM. That's essentially a graph of all states, with each node annotated with the value of the registers in that state, and edges between states that are visited in succession. This graph will have a cycle, and I'm asking about the period of that cycle. It's a question that is a lot more trivial than you may think. Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 (edited) for 3 clock cycles I get a 1 after that I get a 0 for 7 clock cycles repeat. for the FSM I'm currently working on, I get a 1 for 868 clock cycles then 0 for 868 clock cycles repeat. Edited September 5, 2023 by GalD101 Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 Here's the first few states of that state graph. Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 Just now, reddish said: Here's the first few states of that state graph. yeah I drew something similar Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 2 minutes ago, GalD101 said: for 3 clock cycles I get a 1 after that I get a 0 for 7 clock cycles repeat. for the FSM I'm currently working on, I get a 1 for 868 clock cycles then 0 for 868 clock cycles repeat. So, what does that mean in terms of the period of the state machines...? Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 what do you mean by period? how often does the output changes? Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 Just now, GalD101 said: what do you mean by period? how often does the output changes? I defined it above. The period is the number of states the FSM goes through (one per clock cycle) before it ends up in exactly the same state (and, henceforth, will keep on repeating the same cycles over and over again). It's the length of the cycle in the FSM's state diagram. Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 OK so the first one has a period of 10 since it does 1 1 1 0 0 0 0 0 0 0 and then repeats. Similarly, the second one has a period of 868*2 since it outputs 1 1 1 1... 868 times and then 0 0 0 0... 868 times and then repeats Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 Good! That wasn't so hard was it. Periodicity is a pretty important concept in state machines. Good that we figured out this concept didn't come natural to you. We may need it in the future. Okay, so your assertion is that the second FSM has a period of 2 * 868 = 1736 clock cycles. I agree that's what it should do. Now back to the code you posted, with two bugs: wire [3:0] next_counter = (r_counter + 1) % (868*2 + 1); wire next_fsm_out = (next_counter < 868) ? 1 : 0; What values does r_counter take on during a full cycle? And how many different values are that? Does that fit in 1736 cycles? Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 4 minutes ago, reddish said: Good! That wasn't so hard was it. Periodicity is a pretty important concept in state machines. Good that we figured out this concept didn't come natural to you. We may need it in the future. Okay, so your assertion is that the second FSM has a period of 2 * 868 = 1736 clock cycles. I agree that's what it should do. Now back to the code you posted, with two bugs: wire [3:0] next_counter = (r_counter + 1) % (868*2 + 1); wire next_fsm_out = (next_counter < 868) ? 1 : 0; What values does r_counter take on during a full cycle? And how many different values are that? Does that fit in 1736 cycles? it ranges from 0 to 1736 so 1737 different values. I still don't get the problem with this code: wire [10:0] next_counter = (r_counter + 1) % (11'd1738); wire next_fsm_out = (next_counter < 10'd867) ? 1'b1 : 1'b0; Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 > it ranges from 0 to 1736 so 1737 different values. So just one question remains, which you skipped: does that fit in 1736 cycles?While going through N cycles, can a state variable take on more than N distinct values? (We'll get to your updated version later. It fixes the first bug but unfortunately, it introduces another one.) Sorry for pestering you about these details, but when programming, details matter. Link to comment Share on other sites More sharing options...
GalD101 Posted September 5, 2023 Author Share Posted September 5, 2023 1 minute ago, reddish said: does that fit in 1736 cycles? no.... Link to comment Share on other sites More sharing options...
Guest Posted September 5, 2023 Share Posted September 5, 2023 (edited) 20 minutes ago, GalD101 said: no.... So we arrive at a contradiction. You say the r_counter variable takes on 1737 different values but the cycle length of your FSM should by design be 1736, so one of its registers can never take on 1737 distinct values during one full period. We can conclude that this implementation is inconsistent with the intended design. QED. It's a bit heavy-handed to mathematically prove that the implementation is not correct. Let's get back down to earth. Your original version had: wire [3:0] next_counter = (r_counter + 1) % (868*2 + 1); which should have been wire [3:0] next_counter = (r_counter + 1) % (868*2); Your modulus has an off-by-one error. This makes the period of your state machine 1737 rather than 1736, which is not what you intend to do. Your newly proposed version fixes this specific problem, but it introduces another off-by-one error, in this line: wire next_fsm_out = (next_counter < 10'd867) ? 1'b1 : 1'b0; I hope you see it. The gateway question is: per 1736-cycle period, how many cycles with FSM_OUT = 1'b1 do you want? And how many do you get, according to the line above? Count them. These off-by-one errors suck. They are prevalent in normal programming, and also in HDL programming, and they can make your design not work and lead to super hard-to-debug problems. I urge you to get into the habit of becoming very careful about counting stuff. By the way: I don't think your insistence on using bitlength-prefixed integer literals improves readability; rather to the contrary. But do as you please. Edited September 5, 2023 by reddish Link to comment Share on other sites More sharing options...
Guest Posted September 6, 2023 Share Posted September 6, 2023 (edited) Hi @GalD101 Okay, I've been doing a bit of a whirlwind tour through Verilog. In particular, I've read Chapter 4 of this: Digital Design and Computer Architecture, 2nd edition, by Harris and Harris. It's a great intro into SystemVerilog, because they have VHDL/SystemVerilog code examples side by side, allowing me to see the differences and similarities. Highly recommended reading! And to know that it has been sitting on my bookshelf for a few years, tssk. What I got out of this book is that we've been using old-school Verilog, and that's essentially archaic. SystemVerilog has been around since 2008/2009, and the tool support has been slow to pick up (as always), but it's mostly there at this point. Vivado supports SystemVerilog just fine. Some key highlights of SystemVerilog relative to old-school Verilog: No more wire and reg distinction. The standards committee realized the confusion they caused and subsumed their functionality in a new type: logic. Proper ability to define struct types (or "record" types, as we know them in VHDL). Also, enum types. Proper support for functions. The generic always block is still available, but now there are more specialized variants like always_ff and always_comb that indicate the programmer's intent to either implement sequential or combinatorial logic. This allows the compiler to do a lot of error checking, preventing unintended instantiation of flip-flops, latches, etc, which is a big cause of grief. Not too elegant, but super useful in practice. Source files end in ".sv" rather than ".v" ... :-) These changes allow me to write code in a style that is very close to what I am used to in VHDL. So I would propose we switch over to SystemVerilog. It's pretty painless, I already ported the examples on my side. If you agree, I will post my latest versions and we can proceed to use SystemVerilog going forward. The added expressiveness will save us a lot of time. Edited September 6, 2023 by reddish Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 Of course. I'll be looking into it Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 (edited) Is it kind of like a superset of Verilog? Similar to how C++ is (kind of) a superset of C Edited September 6, 2023 by GalD101 kinda Link to comment Share on other sites More sharing options...
Guest Posted September 6, 2023 Share Posted September 6, 2023 Okay here's the test FSM in SystemVerilog. It may be best to just start a new project in Vivado and add these as SystemVerilog files (using the drop-down menu). Have a good look, especially at my_first_fsm.sv; it changed quite a bit to take advantage of the nice new things available in SystemVerilog. This is essentially the style I use all the time in VHDL: define register struct and a reset constant; define a next_state transition function; define the state update (using the always_ff), and hook state registers into output ports. It may take some getting used to, but this implementation style is powerful and clean as you get used to it; Mostly so, because in the "next_state" function, you can just think in terms of semantics that you're used to in regular programming languages. Specifically, assignments have an immediate effect, and the code in the function body is executed front-to-end. That takes much of the confusion out of HDL design. Let this digest for a bit and let me know if you get this up and running. I'll be offline for a couple of hours. clock_synthesizer.sv my_first_fsm.sv toplevel.sv Link to comment Share on other sites More sharing options...
Guest Posted September 6, 2023 Share Posted September 6, 2023 1 minute ago, GalD101 said: Is it kind of like a superset of Verilog? Similar to how C++ is a superset of C Pretty much. Although I must object to the statement that C++ is a superset of C, it is not (quite), if you're pedantic enough. And I am nothing if not pedantic :) Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 That seems to be useful too though I haven't read all of it yet Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 I looked up always_ff and it seems to be just like the regular always but with restrictions. A bit of an unrelated question: in our case, the good old reg (now logic) will be flipflops only (that is, we will only use ffs for memory (reg)? because I think I once saw that it's also possible to use LUTs instead?) It says that "A always_ff procedure adds a restriction that it can contain one and only one event control and no blocking timing controls" and that "Variables written on the left-hand side of assignments within always_ff... cannot be written by other processes". Why did you choose to use an "always_ff" block in line 44 of my_first_fsm.sv? Also, in line 44, why won't you add a negedge or posedge of the reset to the sensitivity list like so? always_ff @ (posedge CLK or negedge RESET) state <= next_state(state, RESET); I now read a bit about event control and it says on the quote above that always_ff can only use one - so is that the reason you didn't add another event (negedge RESET) to the sensitivity list? because always_ff doesn't allow to? I just want to make sure I understand what event control is. As for "blocking timing controls" is it that thing you mentioned before (blocking assignments (=) and nonblocking assignments (<=)?) so that is why you used a function that does these operations instead? Also, why did you use a blocking assignment inside the function? I thought we need it to happen simultaneously, or is it because the function is running sequentially but when you do the nonblocking assignment later on line 44 it runs the function and once it's finished you assign it with <= to "state" so it doesn't matter if you did blocking assignments (=) inside the body of the function because you "fix" it when you use non blocking assignment later on line 44? Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 1 minute ago, GalD101 said: because always_ff doesn't allow to? I think I didn't understand what "event control" is since I found an example with always_ff that has more than one "event" on it's sensitivity list Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 I also find it a bit confusing that there is no longer a distinction between a reg and a wire with the logic keyword. but it's probably because I'm new to it Link to comment Share on other sites More sharing options...
GalD101 Posted September 6, 2023 Author Share Posted September 6, 2023 (edited) Another unrelated question that came across my mind (I'm using the clocking wizard again to generate a 100MHz clock). Why can't I choose a value of M to be 25 and D to be 3 instead of 50 and 6 respectively? Is it just cause or is there a deeper reason as to why, after all 50/6 = 25/3 Edited September 6, 2023 by GalD101 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now