Jump to content

GalD101

Members
  • Posts

    107
  • Joined

  • Last visited

Everything posted by GalD101

  1. I have no clue how to. Do I need to change the series of bits so that will "blink" (switch from 0 to 1 or vice versa) at that frequency? (115200Hz)
  2. Does that involves only changing the sequence of bits I generate? How did you arrive at this number? I think I get how the program works I just don't get what the sequence of ones and zeros essentially means. Does it mean that my output will generate a current for 30 ns and then no current for 70ns and repeating like so?
  3. I also found this video that explains what a FSM is
  4. TBH, I don't really understand the clocksynth.v that you wrote or the one I generated (module clk_wiz_0_clk_wiz). I get some of it by reading and it makes sense but there seem to be a lot of instances of modules I'm unfamiliar with and parameters that I don't understand what is their purpose. I just see it as a black box that generates a 100MHz clock and I use it as a layer of abstraction. As for the toplevel.v and the my_first_fsm.v, well they seem a lot more user friendly. The toplevel design is, as the name suggest a lot more top level (higher level of abstraction). you declared a module that receives the original 12 MHz clock the FPGA provides, and an output that will be one of the pins on the FPGA. you created a "variable" wire called clock that will be our desired 100 MHz clock. you made it a wire(which is a net) and not a reg since this is not memory (reg is used to store things and wire/nets, like a real wire is in charge of making sure that whatever is connected to it (assigned to it) has the same value that we assign it (so you can think about it like you physically connected a wire to the clk. Then you wanted your clk variable to act as a 100MHz clock, so you used your prebuilt module clocksynth to create an instance with the output of this module(CLK_OUT_100MHz) receiving the clk variable you declared (in practice I will also have to set the clk variable to match with a physical pin on the XDC file) (question: why do these instances need names? maybe to use them as input parameters to another module DELETE THIS AND GOOGLE INSTEAD - answer according to google: we can have multiple instance of same module in the same program). Then you instantiated your finite state machine that receives the 100MHz clock and an output pin. This is all, as the name suggests toplevel and there isn't really a lot of logic displayed here (but that's the beauty of it, isn't it?) also it's very reminiscent of OOP in a way. As for the my_first_fsm module, well here the logic hides. you created a module that receives a clk (should be a 100MHz clock in our case) as input and an output which is the finite state machine output. you now created 2 registers "variables" and you made them a register since you want them to act like memory, you want to be able to store information on these variables. you created a "vector" of size 4 bits that uses address 0 through 3 inclusive and assigned it to 0 (I think you should write it like this if you want to be more explicit: reg [3:0] r_counter = 4'b0000; reg [3:0] r_counter = 4'b0; I think the latter is a bit cleaner. And I think the leftmost number (before the ' symbol) represents the number of bits (we need 4 in our case since were using 0 through 3). Then, after the ' symbol, you specify which base you want to use (nothing or d for decimal, b for binary and so on) in short: <size>'<radix><value> ). You gave it a size of 4 bits since you want to be able to store integers from 0 to 9 and while 3 bits won't suffice (2^3 -1 = 7<=9). 4 on the other hand will (2^4 -1 = 15>=9). Then you created another register r_fsm_out that will later be used as the output and its value will depend on r_counter. you gave it a value of 1 (since in the sequence you want to generate 1 1 1 0 0 0 0 0 0 0 there is indeed a 1 on the first bit) also I think that also here you can use a similar syntax as I explained above (1'b1). Now you created 2 wires that will depend on the value of the aforementioned registers. They are wires since you don't want them to be used as memory. You already have the registers for that, now what you did with the logic in the assignment is, sort of like connecting a wire to the registers that does logic to what it receives from the register and implements it, so the values of next_counter and next_fsm_out will always be in accordance to the values stored in the registers. It's like physically connecting a wire. This is how this HDL thing differs from regular programming. It's more of a design of things that happens in parallel more than sequential, row by row as you can see in high level languages such as C or python. In the next part, you created an always block (and this part does resemble programming languages a bit more). You simply made sure that on every positive edge of your 100MHz clock (which will be 10ns?) you will update the value of the registers. You used the non blocking assignment (<=) since you want those two assignments to happen simultaneously because if you were to use blocking assignments (=) so much like in a normal programming language, you will make the assignments sequentially, meaning that r_counter will be updated first and only when that operation is finished then you will alter the value of r_fsm_out. This would create some pretty unexpected output, since we can easily see that r_fsm_out is dependent on next_fsm_out, which depends on next_counter which depends on r_counter so that means that, by transitivity, r_fsm_out depends on r_counter so if we will execute these commands in sequence rather than parallel, we will encounter some unexpected results and out program won't work as we expect it to. That is why we have to use non blocking assignments. We want the assignments to be parallel and not sequential. Then in the end you assign your output value (FSM_OUT) to be whatever is stored in r_fsm_out. a small question, can't you just make your output (FSM_OUT) a reg and then you wont have to use another auxiliary variable(r_fsm_out)? Also, I am pretty sure that Verilog is weakly typed so you don't have to specify types, but shouldn't you specify your input CLK as a wire and your output (FSM_OUT) as a reg? As I said above, I think you can also use less variables if you will do that but perhaps there is a reason for this, also maybe it's cleaner to use another variable, especially in more complex designs.
  5. Unfortunately, as of now I don't really have access to the oscilloscope🙁
  6. can I just ask why you decided to generate 1 1 1 0 0 0 0 0 0 0 ? is it because this is 3(ones)/10(total) so 30%?
  7. I can borrow the other one you saw in the picture. That one is 350MHz
  8. so how will I count 10ns? I think I got confused. Why is changing the clock to operate at 100MHz was necessary in the first place? was it so we will be able to get a better resolution when we will eventually try to capture coincidences? Thank you in advance and thanks a lot for today and thank you in general. this type of thing is quite hard to grasp alone, and it seems I misunderstood some concepts so thank you for the help and dedication
  9. So the next step is to now create a module that implements the logic you described above? the one with the python code? when I started reading about verilog I saw a few tutorials about how to create a testbench. It seems like something I would like to learn but you're probably right, it's better to skip it for now.
  10. p.s. would I need the oscilloscope going forward? because I need to know if I should give it back to my professor or not
  11. Is this what I sort of need to do now? I just want to see if I'm on the same page as you. 1. create a clock divider that makes the counter go up by one every 10ns (probably using an always block and figuring out how many 'ticks' of the 100MHz clock correspond to 10 ns) 2. create an always block that on every posedge of the counter (I think? basically a block that will run every time the value of counter changes) will make the necessary changes to the FSM_OUT. 3. Finally assign the values of FSM_OUT to something else
  12. Do I need to create a new project or should I continue with the same one I created the 100MHz clock with? Should I create a new file (and module) that instantiates an instance of the clk_wiz_0_clk_wiz module I made just with different parameters for the reset, locked and the two clocks? (in a way that resembles OOP?) and then somehow interact with the memory (in this case the ff?)
  13. def fsm_combinatorial_logic(COUNTER: int, FSM_OUT: int) -> tuple[int, int]: # Calculate here values for NEW_COUNTER and NEW_FSM_OUT. # Extra challenge: you cannot change the current values of COUNTER and FSM_OUT! NEW_COUNTER = (COUNTER + 1) % 9 # Fill in this NEW_FSM_OUT = 1 if COUNTER in (0, 1, 2) else 0 # And this # Return the values. return (NEW_COUNTER, NEW_FSM_OUT)
  14. can you please elaborate on this? What do you mean by generating this stream of bits? how do I actually achieve this?
  15. I moved the cable a bit and now it looks a bit more smooth
  16. I got another one that is 350MHz. This is what I got but for some reason it looks a bit different than yours
  17. so all that is left to do now is to synthesize the code, run implementation, generate bit stream, program the device and connect pio26 to the oscilloscope and hope for a sine wave to show up?
  18. I changed the clock in the xdc file: set_property -dict { PACKAGE_PIN M9 IOSTANDARD LVCMOS33 } [get_ports { CLK_IN_12MHz }]; #IO_L13P_T2_MRCC_14 Sch=gclk create_clock -add -name sys_clk_pin -period 83.33 -waveform {0 41.66} [get_ports { CLK_IN_12MHz }]; set the clockout to pio26 set_property -dict { PACKAGE_PIN L14 IOSTANDARD LVCMOS33 } [get_ports { CLK_OUT_100MHz }]; #IO_L7N_T1_D10_14 Sch=pio[26] and that should be it for the constraints file correct?
  19. done. so I should instantiate it to 0 similar to reset? (.locked(0))
  20. you earlier proposed to use a duty cycle of 30%. May I ask what is the meaning of it and why does it need to be 50%?
  21. I think I understand, I need to instantiate a module of clk_wiz_0_clk_wiz in a new file which I'll name top.v like so: clk_wiz_0_clk_wiz clk_wiz_instance ( .clk_out1(CLK_OUT1), .reset(RESET), .locked(LOCKED), .clk_in1(CLK_IN1) ) The question is, what values should I supply to this? (what parameters do I need to supply instead of the capital letter ones?) does CLK_IN1 needs to be the original 12 MHz clock (that is, this one?: set_property -dict { PACKAGE_PIN M9 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L13P_T2_MRCC_14 Sch=gclk) does RESET needs to be a certain btn? what is LOCKED? does CLK_OUT1 needs to be a certain pin of my choice?
×
×
  • Create New...