My first FPGA code - Page 1
Forum section: electronics / general

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 07:07:15 pm
content: Does anybody know why this doesnt work, I took all day to see if I can debug this, it seems I am missing something, there seems to be something after my first always block.Its a simple spi buffer that stores in RAM bits and resets not to overflow.My goal is to compile, wich I cant. And then maybe make a test bench, and mess around in modelsim.This is my code, how off am I in my understanding of verilog?EDIT: Ok, this cpi_rcv.v has no warning, the other warning are just some stuff about top level. I will solve that on my own.Can anybody generally comment on my comments and add some philosophy?I must say this about verilog, I feel like I dont know how to start and am randomly doing things. I chose to learn verilog but I think I was more a VHDL kind of person.---------------------------------------------------------------------------------------------------------------------------------------------------------------Code:module spi_rcv (some_magnitude,some_string); // The way I imagine it These bits should be available for another block with more complex stuff.// I am trying to stay with the youtube lecture of Kirk Weedman and stay organizedinput wire spi_clk;input wire spi_mosi;input wire ram_de; // ram data eneablereg [7:0] i; // some counter, for bit shift, will this be optimized away?//I have visions of a snowplow, plowing away ram bits in sequence, there is no counter in this vision.reg some_magnitude [7:0]; // lets make this interresting, Once ram_de is pressed there is a special 8 bytes in the beginning that is processed differentlyreg some_string [87:0] // there can be many strings later// godtoplevel spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.ram_de(ram_de)); ?? IS THIS REALLY NECESSARY??? SO ANNOYINGalways @(posedge ram_de) begini='b00000000;endalways @(negedge spi_clk) begin // yeah I use negative, because my pin is a neg edge signal, do I GAIN EFFICIENCY in LUTS by doing negedge things with negedge pins??if (ram_de == 1'b1) beginif(i<=7) beginsome_magnitude=spi_mosi; // Some document say I should use non blocking assignement, that its ok to do that.i=i +1; // should I use blocking assignement for line above?, dont wanna skip a RAM bitlocationendelse if(i>7 & i<=87) beginsome_string[i-8]=spi_mosi;i=i+1;endelse if (i>87) begini=0;endendendendmodule

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: November 20, 2019, 07:18:36 pm
content: Try again. Use code tags so thatCode:doesn't get eaten.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 07:48:18 pm
content: Here is my contribution, you cant say I'm a lazy bastard.This is the screen grabs I took manually from Kirk Wedman's lectures in pdf format, this goes with the Kirk Weedman 1-10 video lecture.I bookmarked them in my Ipad1 , goodreader. Is Ipad1 still a thing?http://www.filehost.pt/ay5u~s

author: Yansi
author_rank: Super Contributor
timestamp: November 20, 2019, 07:50:09 pm
content: Again and again and again.Upload images directly to the forum! Pleeeease.Your link is either fucked up, or the website is fucked up, or likely both. It is showing just some irrelevant garbage graphs together with some warnings about "no content for my country". (ノಠ益ಠ)ノ彡┻━┻

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 07:51:21 pm
content: its 37 megsIts 101 pages of manual screen grabs over 1month period. with annotated notes.Its notes that go with the video lecture.

author: 0culus
author_rank: Super Contributor
timestamp: November 20, 2019, 08:29:32 pm
content: I don't have any specific advice for your verilog, but the one thing that made my experience with hardware description language orders of magnitude easier is the realize that it has more in common with wiring up a circuit on the bench than it does with coding. Of course, you do need to make sure you get the syntax right, but outside of that troubleshooting becomes much clearer when you think if it in terms of a literal circuit you are wiring up.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 08:34:33 pm
content: Ok thanks, I have ths image wich helps me alot.Its also about magining little box subsystems and not make useless connections everywhere.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 08:58:01 pm
content: found it! , still have warnings about top level tho. I looked line by line for like 2 hours and never saw it, dumb me. The warning was "always".... something.here it was, can you see it? I thought there was a problem with using two always block, the warning tricked me and also my poor attention to detail.reg some_magnitude [7:0]; // lets make this interresting, Once ram_de is pressed there is a special 8 bytes in the beginning that is processed differentlyreg some_string [87:0] // there can be many strings laterNow that spi_rcv.v compiles without warning, Can somebody review my code and answer my philosophical questions?

author: ejeffrey
author_rank: Super Contributor
timestamp: November 20, 2019, 09:03:54 pm
content: What is it with verilog that makes people unable to indent properly?Your code is actually better than a lot of I have seen, but that isn't saying a lot. Please use consistent and correct indentation!

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 09:40:40 pm
content: Ok, thanks.I actually havent coded in a long long time, I have been so busy with the usual: general research on my schematic+ component research+ PCB design + all the nice thingswith PCB assembly.Now I am coming back to coding, it almost feels like vacaction time, but I guess soon enough I will be back at it

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:02:46 pm
content: Quote from: ejeffrey on November 20, 2019, 09:03:54 pmMaybe I was more a VHDL type of guy?Too late now tho... I hear SV is the futur.I tried to learn "the best language". I dont got enough RAM to learn both VHDL and Verilog.I know C a bit and now verilog a bit, both are supposed to be complementary to eachother.

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:04:13 pm
content: No, reg i probably isn't going to get optimized away completely, though the synthesizer might discover that bit 7 is "stuck at 0" and get rid of it.Philosophically, prefer synchronous designs. Calculate the next state depending on current inputs and let the clock make it the next current state in its time. All non-blocking assignments that take place in tick x are held until all the other tasks scheduled to run in that tick have completed, so that you don't have to worry about ordering statements to avoid it.Rather than switch between two registers of 88 and 8 bits, you could create one 96-bit register and bundle it into wires to split it up, like:Code:wire[7:0] some_magnitude;wire[87:0] some_string;reg[95:0] allmybits;assign {some_string, some_magnitude} = allmybits;The clearer and more straightforward your code is, the more likely that the optimizer will see viable optimizations.Inverters are basically free. For clarity, it is preferable to keep your signals in the true sense (not inverted) within the design and invert at the pins or the edge of the module where necessary. Where you do use inverted-sense signals, it is strongly recommended for your own sanity that you note it in the name with a prefix or suffix.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:14:25 pm
content: Quote from: jhpadjustable on November 20, 2019, 10:04:13 pm

author: asmi
author_rank: Super Contributor
timestamp: November 20, 2019, 10:19:11 pm
content: Never use blocking assignments inside clocked blocks, and non-blocking - in non-clocked (combinatorial) blocks!SystemVerilog allows to make it more explicit with always_ff and always_comb blocks respectively, and will even issue a warning if the code in always_comb block is synthesized into non-combinatorial logic! This warning saved me many-many times from unintentional latches!

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:23:55 pm
content: Quote from: asmi on November 20, 2019, 10:19:11 pmThe issue is not really blocking assignment for a beginner. The issue is that a beginner thinks that there might be a data fuckup since these are not happening one after the other but at the same exact same time and by the inter-relationship of assignements, you anticipate bugs wich are not happening. Because its hard to visualize the data moving, but if you say its safe, and never do that, its good enough for me.wOW ASMI, YOU SOUND SO SMART, CAN WE BE FRIENDS? I'LL MESSAGE YOU EVERYDAY, I'M BUILDING SOMETHING COOL I'LL ONLY ASK YOU SIMPLE QUESTIONS. I'LL ALWAYS REMEMBER YOU

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:45:10 pm
content: Rather than switch between two registers of 88 and 8 bits, you could create one 96-bit register and bundle it into wires to split it up, like:Code:wire[7:0] some_magnitude;wire[87:0] some_string;reg[95:0] allmybits;assign {some_string, some_magnitude} = allmybits;The clearer and more straightforward your code is, the more likely that the optimizer will see viable optimizations.-------------------------------------------------------------------------------------------------I could do that but there always 2 or 3 ways to skin a cat and most the the time its best to jsut do it with what seems natural to you and move on because it will be compiled to the same. I looked serial to RAM verilog code and most use a counterWhat if I wanted to add more than just one 88 bit register, like 8 bits deep? 64 bits deep?reg [87:0] some_strings [7:0];

author: hamster_nz
author_rank: Super Contributor
timestamp: November 20, 2019, 10:53:32 pm
content: To help me out I reformatted the indentation... here is he reformatted code:Code:module spi_rcv (some_magnitude,some_string);// The way I imagine it These bits should be available for another block with more complex stuff.// I am trying to stay with the youtube lecture of Kirk Weedman and stay organizedinput wire spi_clk;input wire spi_mosi;input wire ram_de; // ram data eneablereg [7:0] i; // some counter, for bit shift, will this be optimized away?// I have visions of a snowplow, plowing away ram bits in sequence, there is no counter in this vision.reg some_magnitude [7:0]; // lets make this interesting, Once ram_de is pressed there is a special 8 bytes in the beginning that is processed differentlyreg some_string [87:0] // there can be many strings later// godtoplevel spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.ram_de(ram_de)); ?? IS THIS REALLY NECESSARY??? SO ANNOYINGalways @(posedge ram_de) begini='b00000000;endalways @(negedge spi_clk) begin // yeah I use negative, because my pin is a neg edge signal, do I GAIN EFFICIENCY in LUTS by doing negedge things with negedge pins??if (ram_de == 1'b1) beginif(i<=7) beginsome_magnitude = spi_mosi; // Some document say I should use non blocking assignment, that its ok to do that.i = i+1; // should I use blocking assignment for line above?, don't wanna skip a RAM bitlocationend else if(i>7 & i<=87) beginsome_string[i-8] = spi_mosi;i = i+1;end else if (i>87) begini = 0;endendendendmoduleAt least one issue is that 'i' is updated on the posedge of ram_de, and also on the negedge of spi_clk. This will not work as Flipflops only have one clock signal, and can only be triggered by either a negative or positive edge. It will work in simulation but not in H/WAdapting this to use shift registers rather than counters is the way to go IMO. Indexing arrays indicates a 1:n MUX, which is expensive for large values of 'n'.Count the number of cycles that ram_de is asserted, and when you reach 92 move the data from the shift register into the outputs. Also as the benefit that the update is 'atomic' (all bits change at the same time, not one by one).

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:56:49 pm
content: Quote from: lawrence11 on November 20, 2019, 10:14:25 pmNo, no bug in your code. Your comment asked whether i would get optimized away. The answer is not completely, but individual bits might.QuoteSurely you meant <=. No, you didn't. asmi spelled out the rule better than I could at the time. Heed that advice, especially if you're worried about keeping your LUTs down.QuoteAs in, inverters will be mapped into the LUTs or IOBs where needed so you don't need to concern yourself too much with them. Your FPGA's user manual should have a drawing of all the steering muxes and other config-driven logic within each logic element.QuoteAs a general rule, avoid active-low signals in the guts of your design. Anything that should be active-low externally should be inverted in the top file.QuoteSuch as _n, e.g. spibus_memss_n or host_irq_out_n:Code:assign spibus_memss = ~in_spibus_memss_n;assign out_host_irq_n = ~host_irq;QuoteSPI is a bit of a special case, since MISO and MOSI are updated on opposite edges of the same clock pulse. You could invert the slave select at the edge of the design as above, or not. When you do larger designs with lots of emable and other signals flying around, consistent use of positive logic will help understanding. For now, do whatever works for you.As forCode:reg [87:0] some_string [7:0];fair enough.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 10:59:59 pm
content: Quote from: hamster_nz on November 20, 2019, 10:53:32 pmDam, I dont know what you mean, but it sounds really good, so a quick solution would be to have the ram_de to be @negedge as well? Basically making this reset a wired OR scenario inside the fpga?So whats more important, to stick the negedge SPI because spi_clk is connected to a negedge pin on the PCB, or make this a strictly @ posedge thing?I was also imagining an ever expanding need for parallel connections, but what I was really thinking was : Snowplow!Umm, can you code it for me? Pretty please? I'm trying to learn, honestly... But doggy eyes

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 20, 2019, 11:20:19 pm
content: So whats more important/better/more efficient, to stick to the negedge SPI because spi_clk from MCU is connected to a negedge pin on the PCB, or make this a strictly @ posedge thing?I wanted "efficiency". I saw a quare, I put the square in the square.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 21, 2019, 12:24:30 am
content: Quote from: lawrence11 on November 20, 2019, 10:59:59 pmDoggy eyes! oh no! Must help!I'm completely away from anywhere I can test this so hopefully the idea comes across. Also Verilog is not my native HDL, and it has been many months.Most likely bugs- I shift data into to the shift register assuming it is MSB on the wire first. I am most likely wrong. If this is true, then flip:Code:shift_reg <= {shift_reg[94:0] & spi_mosi};toCode:shift_reg <=spi_mosi & shift_reg[95:1]};You will also need to assign the correct bits to your output.- There are setup time requirements for ram_de and spi_mosi - the logic in the FPGA will be working on a fractionally delayed signal (because of delays inside the FPGA), so don't expect it will work faster than a few 10s of MHz.- Simulate to pick up the many "fence post errors" (off-by-one errors) that I haven't thought through.- Has plenty of extra bits that will generate "not needed" warnings (e.g. bit 7 of 'received_bits')Code:module spi_rcv (some_magnitude,some_string);input wire spi_clk;input wire spi_mosi;input wire ram_de;reg [7:0] received_bits;reg shift_reg [95:0];reg some_magnitude [7:0];reg some_string [87:0];always @(negedge spi_clk) begin// Are we receiving the last bit?if (ram_de == 1'b0) begin // Double check nobody drops ram_de on the last bit!if(received_bits == 95) beginsome_magnitude <= shift_reg[94:86];some_string <= shift_reg[94:0] & spi_mosi};endend// Shift into the shift register, no matter whatshift_reg <= {shift_reg[94:0] & spi_mosi}// Count the number of valid bits in the shift registerif (ram_de == 1'b0) beginreceived_bits <= 8'b0;end else if (received_bits != 255) beginreceived_bits <= received_bits+1;endendendmodule

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 21, 2019, 12:35:54 am
content: Wow thanks.Do you agree with this statement? Snowplow!

author: hamster_nz
author_rank: Super Contributor
timestamp: November 21, 2019, 12:40:07 am
content: Quote from: lawrence11 on November 21, 2019, 12:35:54 amI only hear a whooshing sound as that statement flies by...Oh I get it, maybe it is more like snow building up on a roof, that then slides off just as you close the door....

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 21, 2019, 05:16:44 pm
content: Ok heres some of my code, I think I was mistakelnly thinking I can just press ram_de, and restart from zero, as long as ram_de was pressed, while not disturbing the rest of the bits that werefurther than the bytes I decided to write in that time period. But this is non-sensical, if I want this to be efficient in luts, I cant have it both ways, the bits must be pushing themelves, thus affected by the last bit. If I wanna place bit in the 187th bit, I gotta think 187 moves ahead, and If I want to change it, they all have to get flushed either by writing or a reset.I mean... The ram allocating mechanism is not some little robot on tracks that goes up 1 bitram when you say +1, and deposits the data like in the amazon factory, this is not how it works.As such, the word "ram_de" will be changed to "spi_reg_reset". The counter is no longer there, is it seems like its use is redundant from my new POV, the data must be reset, not a counter, my new way of looking at the world.Here is the present code, as I am writing this, new questions arise in my brain, when I compare this particular example, I am still perplexed as to how I would adapt this "wire mentality"into my particular case, I must admit I am not too comfortable with the rules of concatenation and if I am doing this right.Please help me understand WTF I am doing.Edit: I also notice in his code, he resets the data in the register with a <= block assignement. I dont in my code due to the rule of not having blocking assignements in clocked blocks.http://referencedesigner.com/tutorials/verilog/verilog_32.phpCode:module spi_rcv (important_byte,some_connection); // Should I seperate/concatenate now or later? Where should boundary be defined?input wire spi_clk;input wire spi_mosi;input wire reset_spi_reg; ////reg [7:0] spi_limit_switch; dont think this is really necessary, if I can reset all I can get known state.wire [7:0]important_byte; // I seperate and send out all my bits via wires, not another reg, got it.wire [n-8:0]some_connection; // this good?reg [n-1:0]some_string; //parameter n=184;// godtoplevel spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.ram_de(ram_de)); ?? IS THIS REALLY NECESSARY??? SO ANNOYINGalways @(posedge reset_spi_reg) beginsome_string=0;assign{some_connection,important_byte}=some_string;endalways @(negedge spi_clk) begin// yeah I use negative, because my pin is a neg edge signal, do I GAIN EFFICIENCY in LUTS?//doing negedge things with negedge pins?? because if its bad I'll just use posedgeif (reset_spi_reg == 0) begin //some_string<={some_connection,important_byte};// Ok, we are using blocking assignement+ a concatenation.//how to adapt this line to my situation?//I read this is bad, so is this an exeption, due to chain nature??assign {some_connection,important_byte}={spi_mosi, some_string[n-1:1]};// Hmm, again, how to adapt this line// to my situation?endend

author: hamster_nz
author_rank: Super Contributor
timestamp: November 21, 2019, 08:37:50 pm
content: You need to go back to basics, and describe succinctly what you are trying to do. In your current code you don't use spi_mosi at all, so I am not sure it acutally does anythingYour questions in image..> "Is his[or her] reset technique superior to mine?"Yes. It is the design pattern that the synthesis tools are expected to see. I am not sure if the 'negedge reset' is correct. Resets are usually level sensitive not edge sensitive - otherwise how can you hold the design in reset, because an edge only happens at a point in time.> "Do I need to do this?"Looks weird to me - I have never seen the concatenation on the left hand side of the equals. But it only depends on what you want your reset state needs to be.> "Yeah OK, but I got 2 separate data types..."Verilog is a loosely typed language, and everything is bits and wires in the H/W, so you only have one datatype. In the HDL are describing how the bits flow in the hardware, What those bits acutally mean (i.e. the datatype) is all in the eyes of the designer. The HDL is pretty 'meh' on everything to do with data types.The the problem I see is that you don't seem to have a clear idea of the end result you are trying to achieve(which is OK, because you are building up experience and learning as you go)Here is how I would describe whatI assumeyou are trying to do:QuoteIs any of that wrong? Do you disagree with anything in that spec?PS. please check the formatting of your code you post. Your indentation is really hard to read.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 21, 2019, 09:50:28 pm
content: Quote from: hamster_nz on November 21, 2019, 08:37:50 pmThanks you hamster, I love these sort of discussions, they are very elightening.But I am confused by what you said, because I am just using the same method that he is usinghttp://referencedesigner.com/tutorials/verilog/verilog_32.phpHe writes : assign r_next = {s_in, r_reg[N-1:1]}; ------> I write: assign {some_connection,important_byte}={spi_mosi, some_string[n-1:1]};Basically the same as he, but since I have 2 different datatypes I concatenate immediatly. What am I suposed to do to be like him but seperate my some_string before I make it available forhigher up modules. I am just trying to apply an example to my case, wich is a bit different.module spi_rcv (important_byte,some_connection);Like I said, should I totally ignore any organization, just 1 contiguous register, externalize those wires in my module, then bit mask in the higher up module the 8 bit and 176 bits there.Like this----> module spi_rcv (all_my_wires);

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 21, 2019, 10:26:51 pm
content: Ok Hamster, is this a better form of reset? Or does it absolutely should be be tied to the spi_clock edge occurence? Am I...incuring latches due to timing bullshit if I use an asynch reset??If so hurray !!!!, Latches... Yeah!!! awesome. I'll never get that I said to myself, that's just complicated stuff experts deal with.Code:always begin //here I guess I am just using the fastest internal clock possible?if (reset_spi_reg=='b1) beginsome_string<=0; //assign{some_connection,important_byte}=some_string; // Is this even relevant since I should have a reset line across every ram bit? I'm confusedendendalways @(negedge spi_clk) begin// yeah I use negative, because my pin is a neg edge signal, do I GAIN EFFICIENCY in LUTS?//doing negedge things with negedge pins?? because if its bad I'll just use posedgeif (reset_spi_reg == 0) begin //

author: hamster_nz
author_rank: Super Contributor
timestamp: November 21, 2019, 11:31:17 pm
content: Quote from: lawrence11 on November 21, 2019, 10:26:51 pmIt still isn't the design pattern that the synthesis tools expect.For your chosen FPGA platform you want to find the equivalent 'style guide' - for Xilinx Vivado it ishttps://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug901-vivado-synthesis.pdfand for Altera it ishttps://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/qts/qts_qii51007.pdf.As a gross simplification, the tools look for these patterns and then maps them onto the FPGA hardware. If you use the pattern the tool is expecting to see, you get the result you are hoping for.And it is also the same pattern that other HDL writers are expecting to see, and so will intuitively understand - if you do something in an odd way, people will start looking at the code sideways as they try to work out what patterns you are using.The recommended pattern for Vivado for something with inputs ("DI"), outputs ("DO"), an asynchronous reset ("ARST") and a clock ("CLK") is:Code:module EXAMPLE (DI, CLK, ARST, DO);input [7:0] DI;input CLK, ARST;output [7:0] DO;reg [7:0] DO;always @(posedge CLK or posedge ARST)beginif (ARST == 1'b1)DO <= 8'b00000000;elseDO <= DI;endmoduleend(so I stand corrected on using the "posedge" on a reset signal is the recommended way).I must also point out that you don't use lots of these tiny five snippets to build your design - you merge the patterns into each other where it makes sense, and cross your fingers and hope that you don't give the synthesis tools the wrong ideas.You also don't have to follow these patterns, but things work a lot smoother if you do.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 22, 2019, 02:09:33 am
content: Here is what I wantSave some stuff in a register, that can be reset to 0, and pass it to a main_design.=, in parallel format.It would be nice to use block ram? Like I know these are flip flopsl, but there is alot more ram bits than there is flip flops.Can I make this with ram bits and just have a some_string[2000:0], AND also somehow have a parallel connection on this ram, If I just access a single supreme datatype.Because you "cant access" more than 2 things at the same time using RAM, but what if you only access "one huge thing".

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2019, 03:10:31 am
content: Well that is literally this:Code:`timescale 1ns / 1psmodule spi_rcv(input spi_clk,input spi_reset,input spi_mosi,output [7:0] important,output [15:0] the_rest);reg [23:0] shift_reg;assign important = shift_reg[23:16];assign the_rest = shift_reg[15:0];always @(negedge spi_clk or negedge spi_reset)beginif(spi_reset == 1'B0) begin// Reset if spi_reset is lowshift_reg <= 24'b0;end else begin// Must be the falling spi_clk that triggered usshift_reg <= {spi_mosi, shift_reg[23:1]};endendendmodule(I threw it through Xilinx ISE to check syntax was correct and checked resource usage - but didn't test bench it)

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 22, 2019, 03:53:50 am
content: So this is gonna be a strictly flip flop thing, from the looks of it then. I thought this could be stored in ram bits, and then each ram bit could have a parallel connection to some inner logic.Apparently, on the max10, there is only gonna be 1 flip flop per logic element, and there can be max of 25000 logic elements.So if I use 2000 flips flops I use 10% of my logic elements, partly used.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2019, 04:06:58 am
content: Quote from: lawrence11 on November 22, 2019, 03:53:50 amIf you do it this way, yes. If you want access to 2000 bits at thesame time(i.e same clock cycle) you need 2000 storage elements that can beconcurrently accessed. That requires 2000 flip flops. There is nothing particularly wrong with using 2000 FFs though, you might do this if you were trying to match a pattern in an input streamIf you only need to access a few bits at a time, you can write the bits to memory as they arrive, then recall them later.Have a read of this to see what resources you can use in the MAX 10 see this PDF:https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/max-10/m10_architecture.pdf

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 22, 2019, 04:16:35 am
content: So basically, I need 2000 flip flops no matter what, because I need a constant presence of 2000 bits at the same time, wich I do.I was under the impression that I could do a RAM register as wide as I wanted, but I can only access 1 register at a time( saw that in a video), wich in my case was perfect. But still, I need flip flops to store ot to connect in permanence to ram bits.I understand now.I willtryto explore that pdf, but I fear it will be intense, more intense than 1000 page stm32 documents.edit: not so bad this document, not so bad.btw, I notice that quartus compilation report doesnt show me flips flops used, just logic elements, registers, memory bits., but the xilinx compilation report seems to tell people, from images I saw, am I looking at the right place?

author: hamster_nz
author_rank: Super Contributor
timestamp: November 22, 2019, 08:05:02 am
content: Quote from: lawrence11 on November 22, 2019, 04:16:35 amNo, should you need tousethe value stored in all 2000 bits at the same time (i.e. in the same tick of the clock) you need to have 2000 flip flops.If you need to store 2048 bits but only need to access them eight at 8 bits at a time, then you could use a 256x8 RAM memory block.The other slight complication is that (as a rule of thumb) memory blocks can only be initialized when the FPGA is configured/loaded. So you can not reset all 256 entries to zero when the reset signal is asserted. It would take your logic 256 cycles to write zeros to each address in the memory block.Sure, you can code to set every element in the array to zero when reset is asserted, and it will give you slow, bulky logic that will do that rather than using the way-more efficient memory blocks.Once again, you need to choose a design pattern that you know will map onto the physical RAM blocks available in your FPGA. So at least skim-reading the style guide to see what can work is time well spent.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 03:25:24 am
content: Anybody know whats wrong with my code? spi_rcv compiles and was made by hamster_nz, and spi_rcv_tb is my testbench code, it was made by me and doesnt work.Hamster, how would you do this? with a $readmemb please, I wanna test this feature.So I started by assign variable=1 or0, and then 1'b1 and 1'b0, still not workCode:module spi_rcv(input spi_clk,input spi_reset,input spi_mosi,output [7:0] important,output [15:0] the_rest);reg [23:0] shift_reg;assign important = shift_reg[23:16];assign the_rest = shift_reg[15:0];always @(negedge spi_clk or negedge spi_reset)beginif(spi_reset == 1'b0) begin// Reset if spi_reset is lowshift_reg <= 24'b0;end else begin// Must be the falling spi_clk that triggered usshift_reg <= {spi_mosi, shift_reg[23:1]};endendendmoduleCode:`timescale 1ns/100psmodule spi_rcv_tb;wire spi_clk,spi_mosi,spi_reset;reg [h:0] message;parameter h=23;reg [15:0] bit_indexer;// not used now, using a local reg inside task.spi_rcv spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.spi_reset(spi_reset));initialbegin$readmemb("message.txt",message);assign spi_reset=1'b1;assign spi_clk=1'b1;endtask send_spi_task;reg [15:0] i; // indexer can I initialize here?reg [7:0] f;// frequency in ns can I initialize here?begini=0; // or here?f=50; // or here?if(i<h+1) beginassign spi_clk=1'b1;assign spi_mosi=message; // how to express in terms of 1'b1 or 1'b0???#50assign spi_clk=1'b0;i=i+1;#50;endendendtaskendmodule

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 03:31:31 am
content: heres another contribution, another nice image I made.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 23, 2019, 08:52:13 am
content: I am not experienced at Verilog test benches. But this should get you at least started. It is based loosely off of your code:Code:`timescale 1ns/100psmodule spi_rcv_tb;parameter h=23;reg spi_clk,spi_mosi,spi_reset;wire [7:0] important;wire [15:0] the_rest;reg [h:0] message;reg [15:0] i;spi_rcv spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.spi_reset(spi_reset),.important(important),.the_rest(the_rest));initialbegin// $readmemb("message.txt",message);message = 24'b100011000110001100011001;spi_reset = 1'b1;spi_clk = 1'b1;spi_mosi = 1'b0;// A few clocks before resetfor(i = 0; i < 3; i = i + 1) beginspi_clk=1'b1;#50spi_clk=1'b0;#50;end// Assert the resetspi_reset = 1'b0;// A few clocks in resetfor(i = 0; i < 3; i = i + 1) beginspi_clk=1'b1;#50spi_clk=1'b0;#50;end// Release the resetspi_reset = 1'b1;// Now start presenting the datai=0; // or here?f=50; // or here?for(i = 0; i < 30; i = i + 1) beginspi_clk=1'b1;if(i<h+1) beginspi_mosi=message; // how to express in terms of 1'b1 or 1'b0???end#50spi_clk=1'b0;i=i+1;#50;end// Test bench finished$finish;endendmoduleIt doesn't test everything - just that the reset works and that data bits are clocked through the shift register, (matching your image for what you are trying to implement).I didn't include using '$readmem' because:a) You know what you want to do (use "$readmem()"), but not how to do it. That doesn't add up. Somebody who is as new to Verilog as you are would not have thought of this, however you know the precise name of the function.b) You have far more pressing things to work on than reading data from external files. For now stick with using data declared explicitly in your test bench.c) File names and locations will be different depending on the tools you are using and how you have set your project up. I don't want to make more problems finding out where you should put your data files during simulation when using your toolset.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 04:53:27 pm
content: Thanks hamster , as always.But honestly I am getting frustrated by this language, I try to follow documents, watch videos, read notes, wich say in testbenches you should use tasks.They assign stuff inside the task, just like I do, and I get an error? What gives?Whats wrong on the left hand side, I am doing exactly like they do.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 06:13:49 pm
content: Ok Hamster, I am not satisfied, because I dont understand my mistakes. But since you dont use Verilog I guess this is hard for you.I read a few things about tasks, Ok , I wanna explore this keyword and see what it does. Some people say you should program testbenches using this.Is anybody here competent enough in Verilog to make a simple test bench, using a "TASK" that doesnt give you error, using this simple spi_rcv that compiles.I dont wanna start off leaving dark corners, and crossing out scary words of a language.And I dont really have any pressing matters, I just wanna mess around and complete a project from A to Z, so that I can mess around further and maybe get good.But if I start off leaving dark corners I cant get good.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 23, 2019, 08:04:23 pm
content: Your code didn't work because you never start the task in your initial block.Seehttps://www.chipverify.com/verilog/verilog-tasks

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 08:12:51 pm
content: Aaaaa, I see. I defined but didnt call. Makes sense. Boy... These compiler messages should say better things honestly, cant they make this an educative experience and provide good messages?Guess we see now who done these things and can spot a problem in 30 seconds, vs the people who cant analyze @ the speed where these questions are nothing but a sentence.Heres another question mark?The whole file compiles but I cant see any pulses. Now I'm thinking my workflow is wrong.edit: oops, sim time. 100psAnyways, I still should see all my stuff from both my modules on the object tab

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 08:17:58 pm
content: fileAAA simulation run time.Anyways I hate this simulator, you cant even clear the dam screen without clicking 3 buttonsstill, why cant I see both my stuff in spi_rcv and spi_rcv in the object tab?Its like, I cant get more than 2 modules in objects?

author: rstofer
author_rank: Super Contributor
timestamp: November 23, 2019, 09:19:14 pm
content: Quote from: lawrence11 on November 23, 2019, 06:13:49 pmIf you want to explore all the corners of Verilog (or anything, really) you better set aside a very long time to do it. There is a natural progression from newbie to expert and time is the main ingredient. And lots of code!It would be better to progress along with a structured set of tutorials and get to these corner conditions when they actually come up. Everybody around here knows more about VHDL than I do yet I can still build complex systems using just a very few features of the language. Sure, all the experts would immediately trounce on my code and show where it is seriously deficient but I don't worry about that because I know the systems actually work.In none of my projects have I ever used a procedure or function. I have never used the simulator either. I write code for synthesis only and I do my debugging with a logic analyzer using actual hardware. Simulation is not hardware!

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 10:24:22 pm
content: I feel like going that route as well, just run it in hardware and probe.Problem is that the synthesis can takes like 15 minutes sometime.I read a thread where somebody took like 7 days to synthesize.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 23, 2019, 11:13:15 pm
content: I know what you are telling yourselves."He is a high maintenance whiny noob boy."WRONG!This is BULLCRAP!Tasks, synthesis, programming style that suit your FPGA...When are they gonna make this simple? And write warnings take more things into account.

author: rstofer
author_rank: Super Contributor
timestamp: November 24, 2019, 12:27:34 am
content: Quote from: lawrence11 on November 23, 2019, 10:24:22 pmWhen I moved from Xilinx ISE to Xilinx Vivado, build time went through the roof. So I built up a faster computer with an I7-7700K and a 1TB SSHD along with 32GB of very fast memory. It's still not instantaneous but it's not bad. I can build a complete RISC processor in less than 3 minutes but the project is only a couple of thousand lines.You aren't going to run into week long builds any time soon or on chips that hobbyists can afford to buy.On the same machine, using ISE, I can build a 10,000 line project in about 2 minutes. That's within my short attention span.Here's why I never got started with simulation: I envisioned a situation where the CPU is booting the OS and a few thousand instruction in, things goes sideways because some instruction had a side effect I didn't code. I wanted the processor to run a factory disk image without modification. I couldn't even figure out how to get to that point in the simulation and since I was using 1-hot encoding on a 120 state FSM, I would have to display 120 signals (or somehow get a hex value) just to know where I was in executing some instruction. I didn't understand how to do that with a test bench so I never bothered to learn how to use the simulator.Simulation of trivial logic blocks seems pretty straightforward. Debugging an entire computer system (CPU, Card Reader, Printer, Typewriter, Keyboard, Disk Drive and Plotter) is a little more involved. I didn't see where simulation brought anything to the dance. It's not like 'wait for 10 ns' synthesizes.Everybody has their own approach. Mine is undoubtedly wrong but it works for me.

author: rstofer
author_rank: Super Contributor
timestamp: November 24, 2019, 12:41:30 am
content: Quote from: lawrence11 on November 23, 2019, 11:13:15 pmOnly the high priests of logic design get into HDL and FPGA or ASIC hardware design. Mere mortals need not apply! Arduino coders aren't even in the same league. Hardware is called hardware because it is hard!Xilinx has a ton of documentation as does every other manufacturer. So, all you have to do is read it! The problem is, you won't understand most of it because you aren't up against a problem that some particular application note deals with. You can realistically only read the ones that apply, when they apply. But it's all out there. There are books, YouTube Videos (kudos to VHDLWhiz.com) and all kinds of training material. Again, it won't stick unless you have an application.I highly recommend newcomers start simple: Build the LC3 (or LC3b) RISC processor from what you can find on the web (it's all there) or from the book by Patt and Patelhttps://www.amazon.com/Introduction-Computing-Systems-Gates-Beyond/dp/0072467509No HDL is given, they build the machine using microcode and this would be a workable solution in some HDL as well. In fact, oversize the microcode store, use a .hex file to include the microcode and the processor is easily expandable. It's a really nice project that includes all of the usual building blocks.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 24, 2019, 12:52:01 am
content: Quote from: rstofer on November 24, 2019, 12:41:30 amI'm just a mere mortal, but I'm like a bulldog mortail, I never let go. I know all I'm missing is a bit of education, now if I had a dedicated teacher to answer my questions, I would become a high priest pretty frikkin fast.Those kids at school got an edge, they ca do the homework and ask questions, whie the rest f us, get stuck in the mud with crap like "documentation".

author: rstofer
author_rank: Super Contributor
timestamp: November 24, 2019, 02:11:04 am
content: Quote from: lawrence11 on November 24, 2019, 12:52:01 amDo you expect the average college professor to know the state-of-the-art in HDL programming? My guess is they max out somewhere just beyond 'blink an LED'. There are exceptions, of course, but I wouldn't count on learning cutting edge stuff in a university setting.The way to do it is to write code. Then watch some videos and see if there are better ways to write code. Each iteration improves on the prior incantation. What is almost certain is that you can't get 10 years experience in much less than 10 years. Read books and see how they coded a similar project.Sure enough, your time will be spent about evenly split between documentation/app notes and writing code.Here is some tutorial stuff from Intel (Altera) that also references prerequisites.https://www.intel.com/content/www/us/en/programmable/support/training/course/ihdl230.htmlPick a project, start writing and when it works, throw it out and do it again with style. The best Fortran programs were written when the programmer dropped the box of punched cards. The story of my life circa 1970...

author: NorthGuy
author_rank: Super Contributor
timestamp: November 24, 2019, 04:25:30 am
content: Quote from: lawrence11 on November 24, 2019, 12:52:01 amAsking questions will not take you very far ... If you don't give up, you will soon get to the point where your questions are best answered by reading "documentation".

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 24, 2019, 04:32:34 pm
content: where hamster's post go?anyways thank you hamster, I am seeing squiggly lines now.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 24, 2019, 09:38:36 pm
content: Why does the addition of "reg" make this compile vs not compile.I have seen plenty people assign leds with just outputLike this guy,@ 5 min 37 he shows his code.knowing I had the same warning yesterday, could this have been the reason it did not compile? Yeah I didnt call the task I know, but the warning was this same one, probably onceI solved that I would have gotten a warning about not calling a task.Is it a good thing to add "reg" whenever this warning pops up?

author: hamster_nz
author_rank: Super Contributor
timestamp: November 24, 2019, 10:38:43 pm
content: Quote from: lawrence11 on November 24, 2019, 09:38:36 pmMy understanding is vague, so I will point you at a reference:http://ftp.smart-dv.com/tidbits/wire_reg.htmlMy mental model for this is that a 'reg' is a storage element, and so you can only set a 'reg' in a clocked context (an '@always' block that has a 'posedge' or 'negedge' sensitivity list).A wire has no associated storage element, so can only set a wire in an "unclocked" context.As per my usual lack of Verilog skills, I may be completely mistaken in this.QuoteIt most likely shows an incomplete understanding of context, but as you get more used to Verilog you will get a feeling when you use each of them.

author: Bassman59
author_rank: Super Contributor
timestamp: November 24, 2019, 10:55:41 pm
content: Quote from: lawrence11 on November 24, 2019, 09:38:36 pmYou need to understand the difference between theregtype and thewiretype.reg, despite its name, does not imply that a register will be created by synthesis. It does imply "storage," though.The basic thing is that the target of assignments in an always block must be ofregtype. The targets of assign (continuous assignment) statements outside of an always block must bewires.Remember that you can use an always block to build combinatorial logic, but the assignment target in that block must be areg.

author: Bassman59
author_rank: Super Contributor
timestamp: November 24, 2019, 10:59:46 pm
content: Quote from: hamster_nz on November 24, 2019, 10:38:43 pmIt does not have to be a clocked always block. You can write combinatorial always blocks in Verilog just like you write combinatorial processes in VHDL. Regardless of whether the block is sensitive to an edge or to any change on a signal, the target of assignment in an always block must be reg -- and it doesn't matter if the assignment is purely combinatorial.This is one of the weird things about Verilog.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 24, 2019, 11:18:57 pm
content: Quote from: Bassman59 on November 24, 2019, 10:59:46 pmOften the easiest way to get the right answer is to state the wrong answer, then wait for somebody to correct you...

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 24, 2019, 11:20:14 pm
content: QuoteSo, what I coded was a combinatorial always block? Anyways good stuff bassman, you dished out some pretty niche knowledge I didnt read about.Please dont delete what you said like hamster did, I will read back this thread, this is turning into a good reference.Hamster, Yeah, I was thinking along those lines. But then I felt this was so redundant to mention this is a reg.Yeah wrong answers, those are the best. It gets the forum wheels turning, egos flared up.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 12:10:46 am
content: Quote from: lawrence11 on November 24, 2019, 11:20:14 pmMy deleted post was a long rambling answer that "knowledge of a HDL language is not the key skill for FPGA success", it is in knowledge of the methods, algorithms, protocols and FPGA device features is what would make you an "FPGA Guru'. The place to get this knowledge is in appnotes, user guides and web pages over the internet.As an example, no amount of study of the Verilog language will teach you how to calculate the sin() function in an FPGA.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 12:59:54 am
content: Have you noticed that Verilog experience seems a little thin around here? There's probably a reason for that and I usually attribute it to the elegance of VHDL. But that's just me... I just don't understand Verilog.Not understanding the difference between a combinatorial always block and a clocked always block is an issue. Why not start at the beginning and work up like everybody else? I haven't read through this entire tutorial but it starts out fairly quick by getting to always blocks in the second page. I have never had any interest in Verilog but I might work through it just to see where it goes.https://www.nandland.com/vhdl/tutorials/tutorial-process-part1.htmlI would highly recommend skipping the simulator while working through the tutorial and just synthesize the design. Synthesis is the only thing that matters and simulation isn't hardware! At the very least, keep the Test Bench separate from the logic module(s) and synthesize the logic. Make sure it produces realizable hardware. You can look at the Schematic by poking enough buttons. For Vivado, it is under Run Synthesis -> Open Synthesized Design -> Schematic.It is useful to know that the sensitivity list is a crutch for the simulator, it means nothing for synthesis although the synthesizer will complain if required signals are omitted but it won't throw an error. The synthesizer doesn't really care, one way or the other, but it does imply that what got synthesized isn't what got simulated. This might be a really big deal.ETA: The author separates the test bench from the logic but then uses `include <filename> to pull it into the test bench. This is fine, it is the same source so if it simulates, there is a high probability that it will synthesize and that can be tested against the <logic file>.v file. Given this separation it is reasonable to use the simulator.

author: colorado.rob
author_rank: Frequent Contributor
timestamp: November 25, 2019, 01:27:12 am
content: Quote from: rstofer on November 25, 2019, 12:59:54 amI have never found a shortage of help on Verilog.I ended up choosing Verilog because A) VHDL reminds me of COBOL (so elegance is certainly in the eye of the beholder here), B) most of the open source tooling I found is based around Verilog and SystemVerilog, and C) the default synthesis language in Vivado HLS is Verilog.I also started out watching a number of Bruce Land's Cornell lectures on YouTube; his classes focus on Verilog. And I spend as much time on /r/FPGA as I do here, so that may color my perception a bit.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 01:37:41 am
content: The testing in simulation vs testing in H/W is an interesting rabbit hole to go explore.I made a Venn Diagram to help explain - (opps - where i put synthesis read "Verilog").There are Verilog techniques that work in simulation but don't work in an FPGA - for example a register that is updated on both the rising and falling edge of a clock.There are things that work in FPGAs but not in Verilog simulation - for example uninitialised registers default to '0' in most FPGA hardware, but show up as 'unknown' and corrupt your simulation. There are quite a few of these.There are things that work in FPGAs and Verilog that doesn't work in VLSI - The use of reset signals begin the biggest one I know of. I hear that moving a design from FPGA to ASIC can be 'a lot of work'.Rstofer likes to work in the orange space - simulations of his code might not match the H/W,I like to work in the intersection of the orange an blue space, where I can test things in simulation before trying in an FPGA.Somebody developing code for commercial use and reuse (e.g. a CPU core) will want to be in the intersection of all three, so their code will work everywhere and in simulation.BUT, and this is the big BUT, if you focus on working only in the blue Verilog simulation region, your code will most likely never work reliably on any FPGAs nor any VLSI/ASIC.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 01:40:03 am
content: WHY?

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 01:43:37 am
content: Quote from: lawrence11 on November 25, 2019, 01:40:03 amIf your question is why are pin_1 and pin_2 shown in Orange?Maybe you need an 'initial' block in "parallel_comp" module?Why are you feeding 'data_clk" as the clock into the "parallel_comp" module? Is it actually ticking? Maybe it should be "spi_clk"....

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 01:48:15 am
content: yeah....Its gonna be another clock, why is this a probem? Cearly this signal is getting seen by the simulator.assign pin_1= 1'b1;Isnt this good enough?What do you want from me Verilog? My body through the window and face splattered on the concrete?

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 01:50:46 am
content: Quote from: lawrence11 on November 25, 2019, 01:48:15 amNo, because "pin_1" start off as undefined, and only gets defined if data_clk is ticking. If you add data_clk to your simulation I think you will see that it isn't ticking, so that code never gets run.PS. Verilog and HDL have a very steep learning curve! Stick with it though!

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 01:59:10 am
content: I initialised it to 1 in the initial block, clearly it should get assigned back to 0 on the posedge no?.So "ticking in an always block" is not the same as assigning to 1 outside an always block, even tho it creates a posedge?

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 02:06:21 am
content: in spi_rcv_tb, the data_clk of parallel_comp should be connected to "spi_clk". At the moment it is connected to data_clk.(e.g ".data_clk(spi_clk)" not ".data_clk(data_clk)") on about the 10th line of spi_rcv_tb.PS. This is most likely not what you really want - if the spi_clk stops ticking you won't perform the last comparison - data will have been loaded into "important_byte" but it needs one more clock edge for the comparison to be performed and assigned into pin_1 or pin_2.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 02:08:00 am
content: It is often said that Verilog is popular in the US and VHDL overseas. Maybe... I think we all start with something, develop skills using it and are loathe to start over. I'm sure if I had been using Verilog for the last 15 years, I would be s strong proponent. Alas, my first blinking LED was written in VHDL and that's where I'll stay. What I should do is take one of my projects and rewrite it in Verilog. You only learn stuff like this from writing code. Lots of it!Even though FORTRAN and COBOL are over 50 years old, they are still in use. True, they are not primary languages but for math and science guys, FORTRAN is still useful. I know the nuclear industry still uses it and I suspect the aerospace industry does as well. Banking is still done with COBOL. In both cases, the languages are tightly focused and highly optimized for their target application. Personally, I have been using FORTRAN for nearly 50 years. Of course I like it! I played with COBOL way back when and it neatly implemented on the computer what people were doing with unit record equipment. Both have aged well!

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 02:10:28 am
content: parallel_comp has nothing to do with spi_clk or spi. The spi is there to fill up the shift register, that is all.Code:`timescale 1ns/100psmodule spi_rcv_tb;parameter h=23;reg spi_clk,data_clk,spi_mosi,spi_reset,pin_1,pin_2;wire [7:0] important;wire [15:0] the_rest;reg [15:0] the_rest_compare;reg [7:0] important_compare;reg [h:0] message;reg [15:0] i;spi_rcv spi_rcv_inst(.spi_clk(spi_clk),.spi_mosi(spi_mosi),.spi_reset(spi_reset),.important(important),.the_rest(the_rest));parallel_comp parallel_comp_inst(.data_clk(data_clk),.important_compare(important_compare),.the_rest_compare(the_rest_compare));initialbegin// $readmemb("message.txt",message);message = 24'b100011000110001100011001;the_rest_compare=16'b1000110001100011;important_compare=8'b00011001;data_clk = 1'b0;pin_1= 1'b1;pin_2= 1'b1;spi_reset = 1'b1;spi_clk = 1'b1;spi_mosi = 1'b0;// A few clocks before resetfor(i = 0; i < 3; i = i + 1) beginspi_clk=1'b1;#50spi_clk=1'b0;#50;end// Assert the resetspi_reset = 1'b0;// A few clocks in resetfor(i = 0; i < 3; i = i + 1) beginspi_clk=1'b1;#50spi_clk=1'b0;#50;end// Release the resetspi_reset = 1'b1;// Now start presenting the datai=0; // or here?//f=50; // or here?for(i = 0; i < 30; i = i + 1) beginspi_clk=1'b1;if(i<h+1) beginspi_mosi=message; // how to express in terms of 1'b1 or 1'b0???end#50spi_clk=1'b0;i=i+1;#50;end// Test bench finisheddata_clk<=1'b1;#50$finish;endendmoduleCode:module spi_rcv(input spi_clk,input spi_reset,input spi_mosi,output [7:0] important,output [15:0] the_rest);reg [23:0] shift_reg;assign important = shift_reg[23:16];assign the_rest = shift_reg[15:0];always @(negedge spi_clk or negedge spi_reset)beginif(spi_reset == 1'b0) begin// Reset if spi_reset is lowshift_reg <= 24'b0;end else begin// Must be the falling spi_clk that triggered usshift_reg <= {spi_mosi, shift_reg[23:1]};endendendmoduleCode:module parallel_comp (important, the_rest,pin_1,pin_2,data_clk,important_compare,the_rest_compare);input[7:0]important;input [15:0]the_rest;input data_clk;output reg pin_1;output reg pin_2;input [7:0] important_compare; // for now these are moduleinput pin to receive it from tb initial block;input [15:0] the_rest_compare; // same as abovealways @ (posedge data_clk) beginif (important_compare==important) beginassign pin_1 = 1'b1;//should there be an end here?endelse begin // and a begin hereassign pin_1 = 1'b0;end // or is it good like this?if (the_rest_compare==the_rest) beginassign pin_2 = 1'b1;//should there be an end here?endelse begin // and a begin hereassign pin_2 = 1'b0;end // or is it good like this?endendmoduleCode:module robot_top(// {ALTERA_ARGS_BEGIN} DO NOT REMOVE THIS LINE!spi_clk,spi_mosi,spi_reset,pin_1,pin_2// {ALTERA_ARGS_END} DO NOT REMOVE THIS LINE!);// {ALTERA_IO_BEGIN} DO NOT REMOVE THIS LINE!inputspi_clk;inputspi_mosi;inputspi_reset;outputpin_1;outputpin_2;// {ALTERA_IO_END} DO NOT REMOVE THIS LINE!// {ALTERA_MODULE_BEGIN} DO NOT REMOVE THIS LINE!// {ALTERA_MODULE_END} DO NOT REMOVE THIS LINE!endmodule

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 02:23:11 am
content: Just to show how ignorant I am about Verilog, I have never seen an 'assign' statement inside a clocked always block. If the signal is to change on the next clock, it should probably look like this:pin_1 <= 1'b1;I usually see 'assign' used to connect wires

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 25, 2019, 02:25:05 am
content: Quote from: rstofer on November 25, 2019, 02:23:11 amSame here. And same level of ignorance of Verilog, but it still looks weird to me.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 02:26:55 am
content: Quote from: lawrence11 on November 25, 2019, 02:10:28 amSo what supplies the source of timing to parallel_comp, and triggering *when* it should the comparison?Because at the moment you only attempt a comparison once, just before finishing the test bench:Code:data_clk<=1'b1;I would be expecting that you would want to do it every time that the spi_clk ticks... (which is also a subtly broken idea)....and as other have pointed out - 'assign' isn't needed in an always block, and might be causing some of your issues.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 02:32:00 am
content: rstofer, siliconI tried that, doesnt not make it go low, clearly the data is different @ that moment.anyways its all here, maybe some of you are rusty on your verilog.lets learn it together.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 02:52:24 am
content: If you haven't already guessed, the passing of time is far more controlled and apparent to the programmer in Verilog. Not only do you have to know what you want to happen, but when you want it to happen.Only in simulation you have the luxury of delays - e.g. the "# 50" for a 50 nanosecond delay.In synchronous digital logic (i.e. 99.9% of all FPGA design) everything that can be realized in hardware is referenced to either a rising or falling edge of a nominated signal. Everything that is referenced to the same signal plays together nicely (it is called a "clock domain"). Different clock domains do not play nicely and you have to be really careful moving information between them to make sure it isn't corrupted.Knowing exactly when things happen is equally important to knowing what is happening - if you get it wrong, things will be broken. This is very different to software programming where you just "do things one after the other" and maybe occasionally synchronize with other threads or processes if you are working on advanced stuff.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 03:50:41 am
content: So, what could be a solution for this type of cross domain issue?

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 03:56:10 am
content: If the test for equality across the data is supposed to be a clocked process (as shown above) then it can be tidied up a bit:Code:`timescale 1ns / 1psmodule Verilog01(input wire test1,input wire test2,input wire test3,input wire test4,output reg out1,output reg out2,input wire clk,input wire reset_n);always @ (posedge clk)beginif (reset_n == 0)beginout1 <= 1'b0;out2 <= 1'b0;endelsebeginif (test1 == test2)out1 <= 1'b1;elseout1 <= 1'b0;if (test3 == test4)out2 <= 1'b1;elseout2 <= 1'b0;end;end;endmoduleFurthermore, the hardware looks right, see attached. No attempt was made to use the actual signals for the project.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 03:58:51 am
content: Quote from: lawrence11 on November 25, 2019, 03:50:41 amThis is well described in the documentation. Usually, there is a two clock delay by running everything through a string of 2 flops clocked by the receiving domain. RTFM, this is one of the steps to priesthood.For what I see of this project, and I clearly don't understand what is going on, I can't see why everything doesn't run off of one clock. I have entire systems, IO devices and CPU, and they all run off of one clock. Divided down, here and there, but one master clock. If I wanted to, I could use the DCM (Digital Clock Manager {Spartan 3}) to clean up the timing. This was old school, it has been upgraded to something else (probably some form of PLL) but I haven't kept track.Have you made a state diagram? Maybe just a transition table? It's hard to see what you are doing - at least for me, I know just about nothing about Verilog.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 04:01:25 am
content: Quote from: lawrence11 on November 25, 2019, 03:50:41 amMainly care and skill, using things like dual clock FIFOs, careful two-way handshaking, Grey counters and more.Nothing specifically "Verilog". Verilog is just the language you implement things in.

author: asmi
author_rank: Super Contributor
timestamp: November 25, 2019, 04:03:42 am
content: As far as I can tell, your problem seems to be that you've bitten more than you can chew, which is why you seem to be permanently confused. Get yourself a good book, or follow some tutorial which would introduce features one-by-one and explain them immediately, and do not throw yourself into a wall of code that does God knows what. For books I would recommend "Digital Design and Computer Architecture: ARM Edition" (bonus points to this book for showing VHDL and SystemVerilog code side-by-side which helps to demonstrate just how much of a crap VHDL is), If you prefer video tutorials, I would highly recommend Russell Merrick's Nandland Go board and a set of excellent video tutorials for it:https://www.nandland.com/goboard/introduction.htmlThis guy is a professional FPGA designer, so he knows what he is talking about, and again, he explains and introduces things slowly so that everyone can keep the pace.What Idon'trecommend is you do it the way you're doing know - get some random code from the Internet that does who knows what, and do some random changes in it hoping that you will understand what's going on. The reality is your won't. Here is something that you probably don't expect to hear - reading (and understanding) someone else's code ishard, in many cases it's much easier to write your own code from scratch then to figure out how someone else's code works. So start from simple things - what is wire, what is LUT, what is flip-flop, how to use all of that in HDL, and slowly build up to more complicated concepts (UART, SPI, I2C, etc.). The most important thing here is to make sure youcompletelyunderstand whatever feature or code you're studying before you move on to something else. Basic concepts of HW design should be crystal-clear to you before you have any chance of understanding anything more complex. It's like an alphabet - you can't use the language until you at least learn it, or like a decimal numbers for math - you can't hope to understand anything in math until you learn how to use numbers.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:12:14 am
content: I already past the level of these uart things.I'm here now, @ the clock crossing domain lesson.No time to waste to go back to beginner stuff, this is way better like I'm doing it now, asking the forum teachers what went wrong in my homework.Like you should do, @ school.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 04:12:39 am
content: That "Digital Design ..." book is excellent! I don't agree about VHDL being crap but that's not the point. It is a very good book. Yes, VHDL is wordy.I just ran across NandLand today and I have started the tutorials. They are very well done!You are spot on about code from the Internet and the difficulty in understanding random code. I have enough trouble reading my own code. One thing: Don't write the most clever code on the planet, it will jump up and bite you in the ass when you come back to it a week later.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:15:35 am
content: This is not code from the internet, this is my code, and its the easiest frikkin example to understand.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 04:19:11 am
content: Quote from: lawrence11 on November 25, 2019, 04:12:14 amTrying not to be rude... I feel you are still way below the level of understanding required to implement a UART from scratch.You should take the advice and get a good book (or even a PDF). There is nothing wrong with learning from a book.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:22:25 am
content: http://hdlexpress.com/Verilog/VT.htmlI have a uart example right here, with a state machine, and tb.first link.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:24:40 am
content: NO, I disagree!

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 04:32:57 am
content: Quote from: lawrence11 on November 25, 2019, 04:22:25 amYes, but you didn't write it. There's a ton of code at OpenCores.org that I can grab - but I didn't write it. And I won't ever really understand how it works because I didn't write it. I can read it until I'm blue in the face but I still won't understand it if I didn't write it. From scratch, no crib sheets.The same goes for tutorials. I don't learn as much just watching the video as I do when I type the code and run it. Simply doing a copy-and-paste doesn't count. Actually typing the code gives the best results - for me.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:51:57 am
content: Yeah it counts, I understand his code. Once I can simulate I can mess around.Its mine now.BUT, he never goes with a hard example, with multi module. how to link many module to 1 test bench. Show me a multi module, 3 module=37 module.1 module=? I am still confused. Clock domain I am still confused.He just says, you gotta work like this.... presents graphs, gives an easy example.So... Are we getting any close to a solution? Is it a double buffering type scenario?

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 05:01:09 am
content: Hey why dont canadians give good answer to fellow canadians?You guys are just trolling me.Dont mind me, I just wanna invent the stuff I was destined to invent.Nobody is gonna hire me, dont worry...

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 07:39:08 am
content: Ok I get it hamster, This is the scenario of double buffering, and you said the time is not accounted for.Are you aying such a buffer would be 1 clock late and to pass from 1 domain to another I need an extra clock thus 2 clocks, and in this particular example the error is evident?End result, I see a sim that has perfectly enough time for the electrons to do its job, but its bugged.What is the recipe to solve this? I must pass the value to an intermediate register?Can we stop being gatekeepers now. I watched the videos, I have it in front of me, I dont get it.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 08:46:09 am
content: Quote from: lawrence11 on November 25, 2019, 07:39:08 amThe data bits are being received when SPI_CLK changes.And do you agree that the design is testing the value of 'important byte' after it is received - the data assembled from bits that receive every time SPI_CLK ticks, and then the received value used for the comparison when the clock next ticks.What happens when the source stops ticking the SPI_CLK signal, because it has sent all the data?Can you see that there is the problem?Maybe an example of what is going on - where the send send 'A', 'B', 'C' & 'D' a minute apart, then waits 56 minutes before send 'E' & 'F':Code:Time Receiving Testing - is it 'D'?0:00 A -0:01 B A0:02 C B0:03 D C... Sender pauses for an 56 minutes, before sending 'E'1:00 E D <<< Yes it was D, but that was 56 minutes ago!1:01 F EDo you agree there is a problem, or have I lost you?

author: emece67
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:31:36 pm
content: .

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 04:56:10 pm
content: Hamster, yeah you have lost me.@ Emece67, These kind of gatekeeping posts have their use, thank you.But I disagree @ your solution, wich is nowhere to be found.I just send this example on reddit and everybody is wrong.https://www.reddit.com/r/FPGA/comments/e1bk0c/please_help_me_understand_verilog_and_a_workflow/Everybody who gives long answers cant find the problem. I think they just dont know verilog enough.You can see here, that people are upvoting wrong answers, and that most people are bad @ Verilog.None of you are smarter than Hamster, so far.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 05:30:16 pm
content: Ok I'll be honest here.I think that about 50% of people who studied Verilog, claim to know Verilog on their resume. Dont really know Verilog and just struggle their whole lives.Dont know the answer and couldnt find the cause/fix if I gave them this file.

author: emece67
author_rank: Frequent Contributor
timestamp: November 25, 2019, 07:45:17 pm
content: .

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 25, 2019, 08:18:56 pm
content: Ok I'm gonna have to digest this. I read about this honestly, but its like chinese almost, I need to really think about it.Thanks alot. I'll have to go and relay this message, in a more understandable format to those people on reddit.Reddit has been going downhill for a longtime now, its as if the xbox crowd moved to /fpga.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 25, 2019, 09:28:22 pm
content: For what it's worth, that junky testbench was written assuming that it really was a SPI connection (with SPI_CSn, SPI_CLK and SPI_MOSI signals) that were being driven by an external device (a microcontroller, a Raspberry Pi, whatever...). If that is the case, the SPI_CLK doesn't have to be continually driven, hence why the whole SPI transaction was in it's own initial block. It it was driven conAt some point a true, independent clock for the FPGA will be needed, along with a proper reset signal (rather than using a SPI signal) , which both deserve their own blocks 'initial' or 'always' blocks in the test bench.For @lawrence11 benefit, attached is the image of a SPI transaction fromhttps://www.analog.com/en/analog-dialogue/articles/introduction-to-spi-interface.htmlwith data sampled on the falling edge and shifted on the rising edge.PS. Oh how I wish SPI didn't have the whole different Clock Polarity and Clock Phase thing... I am yet to get to grips with it, get it wrong 75% of the time.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 09:52:08 pm
content: Using the SPI clock in the FPGA clock domain is problematic. The CSn, Clk and MOSI (assuming the FPGA is the slave) need to be synchronized with the FPGA clock domain. I will assume the FPGA clock is faster than the SPI clock but it doesn't have to be if FIFOs are used.Since my FPGA boards typically run at 50 or 100 MHz, I don't see the SPI clock as being faster so what we have are signals from a slow domain transitioning into a fast domain.Here's how it is done:https://www.nandland.com/articles/crossing-clock-domains-in-an-fpga.htmlYes, it's in VHDL but it translates easily. I would make it a 1 signal in/out module and instantiate it everywhere I had signals coming from outside the FPGA into the FPGA. Or make it generic in terms of width but that's above my pay grade. Note that the code also deals with pulses.Debouncing manual switches is an entirely separate issue.This is one of those cases where the unsynchronized signals will look fine in simulation because the simulator synchronizes everything but in the real world it fails badly.

author: rstofer
author_rank: Super Contributor
timestamp: November 25, 2019, 10:18:43 pm
content: If this code ever starts to look like a FSM (and it probably will), it would be nice to start a timer on the falling edge of CSn and test it for timeout in every state. The transfer is aborted if the timer times out and the code then branches to a state where it waits for CSn to go high before returning to some initial state where it is waiting for CSn to go low. This state where the code waits for CSn to go high will exist anyway, nothing is added. I guess an error flag could be set but so far, this project doesn't have a register style interface. It doesn't look like a controllable peripheral. I'm not saying it has to have a register interface but it's a pretty common idea.

author: Bassman59
author_rank: Super Contributor
timestamp: November 25, 2019, 10:59:01 pm
content: Quote from: colorado.rob on November 25, 2019, 01:27:12 amIn the course of my career, I have had to use both languages ... and the choice of language was made by my employers. That said, now I work for a VHDL house, so by default it is my preference. (Actually, it's always been my preference.)I'm pretty sure that my experience is common.

author: Bassman59
author_rank: Super Contributor
timestamp: November 25, 2019, 11:10:49 pm
content: Quote from: lawrence11 on November 25, 2019, 01:59:10 amHere is the odd thing aboutinitialandalwaysblocks.They run in parallel.I learned Verilog long ago, long enough ago to have used the SILOS III simulator, and to have found a bug in it, and I called them up on the phone and spoke to one of the developers who said, "Yep, that's a bug, look for a fix shortly ..." and one of the things which was pointed out was that theinitialblock is not an initializer block! That is, it was never intended to be something where you stuff all of your signal resets and initializers. But somehow synthesis semantics have made it so.Basically the differences between the two blocks are:a) Theinitialblock cannot have a sensitivity list, which means thatb) it runs only at the start of time and when it suspends it's done. It never goes back up to the top of the block and start executing again, and it needs to have waits and delays to advance time.c) Analwaysblock has a sensitivity list, which means that it wakes up whenever there is a transaction on the signals in its sensitivity list. (If analwaysblock doesn't have a sensitivity list, you need to make sure that there are waits or delays to advance time. It's almost like aninitialblock in that sense but execution jumps back to the start of the block when it reaches the end.)Now if you assign a wire to 1'b1 outside of an always (or initial) block, congratulations, you have made a constant. If you assign to the same signal inside a block and outside, well, you can't do that -- as noted before, signals assigned inside a block (eitherinitialoralways!) must be of reg type; signals assigned outside the block must be wires.To be honest, this sort of silliness (and the whole idea of blocking and non-blocking assignments in a block) is why I prefer VHDL over Verilog, where the semantics of the language are clear.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 12:14:04 am
content: I seem to fail at following directives. I will try implementing the reset after this passes.Can you post the code emece? Or some of it.

author: emece67
author_rank: Frequent Contributor
timestamp: November 26, 2019, 12:16:40 am
content: .

author: emece67
author_rank: Frequent Contributor
timestamp: November 26, 2019, 12:19:39 am
content: .

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 12:40:38 am
content: I read a 50 page document, and more videos.I'm just slow.

author: rstofer
author_rank: Super Contributor
timestamp: November 26, 2019, 12:46:00 am
content: Quote from: Bassman59 on November 25, 2019, 11:10:49 pmAnd it's worth pointing out again, this sensitivity list only starts processes under simulation. It has no effect on synthesis even though the synthesizer complains if signals are missing.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 12:55:56 am
content: I honestly could have been lucky and avoided this, I passed by this solution a bunch of times.But by then, this murderous line was poisoning my workflow.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 01:03:09 am
content: Finally, I have attained....

author: hamster_nz
author_rank: Super Contributor
timestamp: November 26, 2019, 02:02:56 am
content: Quote from: lawrence11 on November 26, 2019, 01:03:09 amWhich dot is yours? I think everybody who has contributed is at the "Trust me, it's complicated" dot.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 02:25:55 am
content: Well' I'm obviously at the peak.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 02:40:35 am
content: Ok can we talk a bit about Verilog vs system verilog?You see in this image, the quick instantiation? Well that is only a system verilog feature. So If I dump verilog right now for system veriog, can I just do EXACTLY what I would do usually but use these quick instantiations? I dont wanna have ti setup anything complicated either in simulation or synthesis.

author: Bassman59
author_rank: Super Contributor
timestamp: November 26, 2019, 04:10:31 pm
content: Quote from: rstofer on November 26, 2019, 12:46:00 amTrue, but not interesting -- I know you don't believe in simulation, but for those of us who do, the sensitivity list matters.

author: rstofer
author_rank: Super Contributor
timestamp: November 26, 2019, 06:56:47 pm
content: Quote from: Bassman59 on November 26, 2019, 04:10:31 pmIt is still required for synthesis so it's important to me as well. It's pretty easy to add logic to a process and overlook including a new signal in the list. I think it's the 'wake up' part that really needs to be clear: The sensitivity list tells the simulator to run a process (always block) when any signal in the list changes. That saves effort for the simulator If it doesn't need to evaluate the block, it doesn't. The synthesizer generates logic for the block taking no information from the list. It's not like the logic under synthesis is 'enabled' by the list as it is in simulation.Since the simulator cares about the list and the synthesizer doesn't, it is possible to get two different implementations of the logic should a signal be omitted.The exception is a clocked process where only the clock needs to be in the list because the clock is always changing and changes in the other signals are evaluated when the clock changes. If the reset signal (if any) is asynchronous, it should be included as well. I don't think it is necessary for synchronous reset but I include it anyway.Now we can use process (all) or always @ (*) to let the simulator and synthesizer work it out for themselves. I'm still trying to figure out whether this is an improvement or just a change. If the software doesn't care about the sensitivity list, how about just omitting them instead of using a crutch?

author: Bassman59
author_rank: Super Contributor
timestamp: November 26, 2019, 09:57:26 pm
content: Quote from: rstofer on November 26, 2019, 06:56:47 pmFor synchronous processes, having a sensitivity list that includes only the clock (and perhaps an async reset) optimizes the simulation. And, I think, it reduces everything to continuous assignments.If a synchronous process (I'm using VHDL vernacular here) doesn't have the restricted sensitivity list, the simulator won't ignore it until there's an event on the clock. Instead, every time there is an event on any right-hand-side signal, the process gets triggered and everything has to be evaluated. And this is even though therising_edge(clk)function will return false and no new assignments are scheduled. Imagine how much simulation time is wasted on such processes.Combinatorial processes of course are sensitive to every signal on their assignments' right-hand-sides, so the (all) sensitivity list is reasonable.(Remember that a continuous assignment outside of a process has an inherent sensitivity list that is all of the signals on the right-hand-side of the assignment.)So specifying the sensitivity list helps the simulator. And, I think, more importantly, it helps the person reading the code by saying, "this process is triggered by this signal." Straightway you see which signal is the clock. It's self-documenting. It's not like there's a lot of typing involved here!All of which is to say that the statement "synthesis doesn't care about sensitivity" is likely (I haven't actually tested this assertion!) true but not very interesting.

author: rstofer
author_rank: Super Contributor
timestamp: November 26, 2019, 10:09:18 pm
content: It seems to get out of hand when you design a 2 process state machine with 100+ states in the combinatorial process. The sensitivity list can get lengthy but the only way to keep the synthesizer from nagging is to add every right-hand-side signal.And, on a different matter, provide a default value for every left-hand-side signal. This is where I have had the most problems. The state machine hangs because there is no value for a signal even though the next-state is clearly defined. Basically, I came up with the idea that 'if it doesn't work, look for missing default values first!'. This is another place where it is easy to mess up when adding additional logic and output signals.Of the long list of mistakes a user can make, I suspect I have hit them all. Maybe I have missed a couple of esoteric problems because I don't use the construct but for everyday logic, I've made them all! I should get a merit badge...

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 10:15:53 pm
content: One more time

author: Bassman59
author_rank: Super Contributor
timestamp: November 26, 2019, 10:56:05 pm
content: Quote from: lawrence11 on November 26, 2019, 10:15:53 pmThe block is clocked by data_clk and data_clk never toggles. If the clock doesn't toggle, pin_1 is never assigned.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 26, 2019, 11:05:05 pm
content: Nah, the problem is far more simple - they are watching 'important' and 'the_rest' in the test bench,, but not passing it into the prallel_comp_inst:Here's the module definition (reformatted):Code:module parallel_comp(important,the_rest,pin_1,pin_2,data_clk,important_compare,the_rest_compare,spi_reset);But where it is used, "important" and "the_rest" are not mapped (reformatted):Code:parallel_comp parallel_comp_inst(.data_clk(data_clk),.important_compare(important_compare),.the_rest_compare(the_rest_compare),.pin_1(pin_1),.pin_2(pin_2));If they were to look at "important" inside the module, rather than in the test bench, it will be undefined.Got to love Verilog

author: Bassman59
author_rank: Super Contributor
timestamp: November 26, 2019, 11:13:55 pm
content: Quote from: rstofer on November 26, 2019, 10:09:18 pmThe usual advice here is "don't write two-process state machines (unless you have a really good reason to do so, and even then think about it some more)." Forgetting to assign to each left-hand-side in each state results in latches. Theprocess(all)construct lets you not worry about the sensitivity list but you still have to make sure that you assign everything in every state.QuoteI'm afraid this is both a tools problem and a device problem. VHDL allows you to write initializers for every signal in your design when those signals are declared. (My Verilog is out-of-date; I assume it has a similar mechanism.) In simulation, it's obvious what happens to those signals.But what happens when the synthesizer gets ahold of them? That all depends.Recall in VHDL the usual initializer:Code:signal foo : std_logic := '1';For example, the Xilinx synthesizer (even in ISE, now still in Vivido) will take the initializer and use it to reset or preset each flip-flop in the designat configuration time. Xilinx recommends never using an asynchronous reset in designs using their devices, so this guarantees that your flip-flops will have a reasonable value immediately after configuration, before any synchronous reset you might use. (What we do here is to use a reset supervisor chip to drive the FPGA's PROGRAM input; release of PROGRAM starts configuration and will basically be a chip-wide reset.)Do other tools and devices support using initializers in this manner? Well, the Actel/MicroSemi devices do not. These devices require an explicit reset to get the to your desired default state. That is, at configuration (these parts have flash-based configuration so that's immediately after power-up) the flip-flops have an unknown state which isnotcontrolled by the VHDL initializer. And worse, at least with the Pro-ASIC3 devices, the flip-flops do not inherently support a synchronous reset (if you code one, you'll get a mux in front of your flip-flip with one side set to the reset/preset value and the other comes from the logic going into it). So you need to provide an external asynchronous reset (which should should synchronize and use that to drive the flip-flops's async reset input) to get everything ready.So at least in the Actel case, you can't use initializers.But in that case, since the design requires an async reset, the test bench should provide one. It doesn't have to be very long, either. This will solve your simulation's "lack of initializer" problem, assuming that all signals that require a reset get one.As to what Intel wants, it's been awhile since I used one of their parts.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 26, 2019, 11:42:59 pm
content: Verilog: When in doubt, instantiate everything like a headless chicken.Even tho its completly unnecessary for the tb instantiation to know what is important since it is defined as wire and testbench has no direct write authority.Its none of its business whats important is, what it should be doing is concentrating on pin_1 like I asked it to.

author: rstofer
author_rank: Super Contributor
timestamp: November 26, 2019, 11:43:57 pm
content: I wasn't thinking about the 'initial' value but rather a default value assigned inside the process, just ahead of the case statement, that provided a value for the named signal in every state unless over-ridden in the state. Given, say, 50 output signals from the FSM, it would be silly to define them in each of 100 states yet all signals must be defined in all states, one way or another. Missing one of these signals results in a latch, something to be avoided.I didn't know that initializers weren't universal. After all, it is just a configuration bit among millions of other bits configuring the fabric. Most of my work has been with Xilinx going back to the Spartan 2 and ISE. Today I was reminded just how good Vivado was when I installed Lattice ICEcube2. I'm thinking about a lengthy tutorial program that uses the ICEstick evaluation board so I'll have to go with the flow. Part of the goal is to understand simulation and the course wants to use ModelSim and ICEcube2. I suppose I could just translate the work to Vivado right off the bat but the results won't identically match the course material. Maybe I'm still undecided...The asynchronous versus synchronous reset issue has been debated since the first FPGA project. I have used mostly asynchronous but if Xilinx says to use synchronous, that's fine. I have done it wrong for a long time but there's still time to learn to do it right. I guess the asynchronous approach came from the 7474 which has asynchronous set and reset.

author: emece67
author_rank: Frequent Contributor
timestamp: November 27, 2019, 04:20:49 pm
content: .

author: rstofer
author_rank: Super Contributor
timestamp: November 27, 2019, 05:18:01 pm
content: I have been thinking about the difference in a single process model and a two process model FSM and it seems to me that I lose 1 cycle due to latency with the single process model.Suppose I just this instant entered a state A in a two process model and with some combinatorial logic, I produce a SEL signal for a MUX outside the FSM. I want the MUX to use the duration of state A to select the proper input such that at the very next clock, the output is registered (potentially somewhere else). If I'm not allowed to output combinarorial logic in a single clocked process, it would seem to me that I need to wait until the following state to use the outputs of the MUX.Is there a way around this latency issue?I'll concede that the single process model is faster because I have two chunks of combinatorial logic that need to be resolved in a single clock cycle but, so far, I haven't run up against a timing issue. Unless the clocked version is twice as fast (and it could be), I don't make up for the time lost due to latency.An example of a clocked MUX might be a program counter. It would have 4 operations (PC_NOP, PC_RESET, PC_LOAD and PC_INCREMENT). The default value in the FSM would be PC_NOP. Just after an instruction fetch, the FSM would send the code for PC_INCREMENT and if we're going to do a branch, the code would be PC_LOAD and the parallel inputs would come from some permutation of the instruction or, perhaps, some register. It seems important to me not to add 1 clock of latency because I may need the PC in the next cycle (eg branch).

author: rstofer
author_rank: Super Contributor
timestamp: November 27, 2019, 05:25:52 pm
content: Quote from: emece67 on November 27, 2019, 04:20:49 pmOne of the best things a newcomer can do is model different blocks, synthesize and review the hardware schematic. What code results in what hardware? I have a book on HDL design that spends a lot of time on the different ways to model various blocks. It's very interesting stuff.I don't know what anyone would expect from PC <= PC + 1; but it isn't some kind of counter. No, Vivado will use a full-adder in the feedback path and just add 1. Now, among the hundreds of options, I suppose there is a way to change that but, by default, Vivado uses an adder. Somehow I think it is important to know that. Later on I'll figure out why it's important...

author: emece67
author_rank: Frequent Contributor
timestamp: November 27, 2019, 06:54:09 pm
content: .

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 27, 2019, 07:20:25 pm
content: QuoteIt looks pretty much like Garbage IMHO.

author: rstofer
author_rank: Super Contributor
timestamp: November 27, 2019, 07:43:07 pm
content: Quote from: emece67 on November 27, 2019, 06:54:09 pm"HDL Chip Design" by Douglas J Smith

author: rstofer
author_rank: Super Contributor
timestamp: November 27, 2019, 07:45:57 pm
content: Quote from: lawrence11 on November 27, 2019, 07:20:25 pmWhat you have is 3 inputs going to IBUFs and 2 outputs going through OBUFs on the way to pins. No logic is included and I'm not sure why. All you have is 3 inputs and 2 outputs connecting to nothing. Sometimes the schematic 'summarizes' what is below and if you double-click on a block, you can drill down. I don't know if that is the case here.I think that some folks liken using an HDL to using a programming language and clearly that is not the case. It would seem to me that a designer using HDL to model a circuit would first need to be proficient with hardware. Can the designer, given a warehouse full of every 74xxx gate ever invented, actually fabricate their design in real hardware? If not, there's a really steep learning curve ahead. My personal limit for wire-wrapping is around 100 chips. Beyond that, I lose patience and focus. 100 Medium Scale Integration (MSI) chips like the 7474 Dual-D Flop is only 200 flops. Not very many when compared to nearly a million in the FPGAs I use. The XC7A100T has 101,440 slices with 8 flops each so around 811,520 flops. I can't even imagine what a similarly sized TTL implementation would look like.https://www.xilinx.com/support/documentation/data_sheets/ds180_7Series_Overview.pdfPage 3

author: rstofer
author_rank: Super Contributor
timestamp: November 27, 2019, 08:08:08 pm
content: Quote from: lawrence11 on November 27, 2019, 07:20:25 pmLook back at Reply 73 where I gave you a simplified version of your 'parallel' code (except I just tested a single bit for simplicity) and look at the resulting hardware. It is pretty easy to get from the HDL to the hardware and the hardware makes sense.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 27, 2019, 08:22:12 pm
content: I started with 74HC,C4000 and now 74LVC.Then I was hesitant to move into uC's tarted with microchip, and from uC's I was hesitant to go into FPGA's.I already drew the circuit, its a flip flop chain connected in parallel woth comparator modules, wich now get the parallel value from an initial block, but in the real circuit it will be real synchronous parallel data.Probably it is lost as to what it should.In any case, I cant babysit some interpretation algorithm in order to get sone sensical data out of it, I prefer extracting the circuit by observing the result, from the simulator.

author: Bassman59
author_rank: Super Contributor
timestamp: November 29, 2019, 11:13:46 pm
content: Quote from: rstofer on November 27, 2019, 05:25:52 pmA counter is a special case of an adder.A full adder allows you to specify the all of the inputs. A counter doesn't, as it uses the output fed back as one of the inputs, and the increment value (in this case, 1) as the other. My guess is that the logic is the same.Also consider that your Xilinx device has hard-core adders (math blocks). The synthesizer knows how many exist and may preferentially fit long counters into one. A 16-bit counter implemented with a hard adder should be faster than one built from slices.

author: Bassman59
author_rank: Super Contributor
timestamp: November 29, 2019, 11:17:07 pm
content: Quote from: emece67 on November 27, 2019, 04:20:49 pmTo be honest, the notion of Mealy vs Moore machines is an academic one. I can't remember which one does what, and it honestly doesn't matter. Write the state machine in the manner which makes the most sense for the design.QuoteThere are no pointers in VHDL so no need to deference one.

author: Bassman59
author_rank: Super Contributor
timestamp: November 29, 2019, 11:18:37 pm
content: Quote from: lawrence11 on November 26, 2019, 11:42:59 pmVerilog makes assumptions about signals which are not connected. VHDL throws errors at compile time. Which do you think is more helpful for the designer?

author: Bassman59
author_rank: Super Contributor
timestamp: November 29, 2019, 11:41:08 pm
content: Quote from: rstofer on November 26, 2019, 11:43:57 pmAh, OK, this distinction between an initializer and a "default" is important.As for "default" assignments in a combinatorial process to avoid latch inference, exactly what is the default? For example, say you have a four-state machine and you assign to signal foo in two of those states. How do you maintain the signal value in the other two states? This is one reason why I avoid the two-process FSM.Yes, the single-process FSM has its one clock of latency. But for most cases this latency is easily handled. Yes, there are exceptions.I do use a clever trick to set the time (in clocks) spent in some states. Remember this is all in a clocked process. I create a signal called duration. Outside of the state machine I have an assignment:Code:if duration > 0 thenduration <= duration - 1;end if;and then in the machine itself I'll have code like:Code:when STATEX =>duration <= 50;foo <= '1';state <= STATEY;when STATEY =>if duration = 0 thenfoo <= '0';state <= STATEZ;end if;Perhaps there's a way to do this in a two-process machine but I don't want to think about it.But whatever works for you.QuoteItshouldbe but it isn't.QuoteThe Xilinx reason for the async reset is that it gets put on a slow global net (GSR) and there's no way to ensure that all flip-flops come out of reset at the same time, especially on the larger chips running fast. And since the flip-flops have resets which are configurable as either async or sync with no penalty for the sync reset (my guess is that the sync reset/preset is nothing more than a mux selected by the reset signal that drives the D input) then it works well. If the flip-flops in the fabric don't have a sync reset capability then it must be implemented outside of the flip-flop (in the CLB or wherever).

author: emece67
author_rank: Frequent Contributor
timestamp: November 30, 2019, 12:21:51 am
content: .

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 12:57:36 am
content: Quote from: Bassman59 on November 29, 2019, 11:13:46 pmXilinx has carry-chain hardware in every slice, so just feeding '1' as a carry to it will generate a counter of decent speed. This is what Vivado uses most of the time.This is not as fast as DSP, which can count faster than carry chain, but DSP's clock speed is limited.Since the state of the counter is fully known as far to the future as you want, you can always pipeline the counter and make it go as fast (or nearly as fast) as the logic can be clocked, which is much faster than DSP. Although it'll take a lot of logic for a long counter.

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 01:01:17 am
content: Quote from: Bassman59 on November 29, 2019, 11:41:08 pmSuppose I implement the program counter as described above and in the combinatorial process of the FSM, I only actually interact with the PC when I want to load or increment which occurs in just a very few of a hundred or so states in the FSM. The default value IAR_NOP is sent to the PC unless otherwise specified. This is the only way, short of defining the output in every state, that will eliminate latches.Here is a simple process for the Instruction Address Register on my IBM1130Code:[font=courier]- IAR controlprocess(Reset, Clk, IAR_Ctrl)beginif Reset = '1' thenIAR <= (others => '0');elsif Clk'event and Clk = '1' thencase IAR_Ctrl iswhen IAR_NOP=> null;when IAR_LOAD=> IAR <= A_BUS;when IAR_INCR=> IAR <= IAR + 1;when others=> null;end case;end if;end process;It is controlled by the main FSM by something like this in state s49:Code:[font=courier]when s49IAR_Ctrl<= IAR_INCR;NextState<= MemRd;The default value set up at the beginning of the combinatorial process does:Code:[font=courier]process (state, FullEA, FetchOpnd, F, TAG, IA, CO, OFL, OVFLInd, COtemp, CSET, VSET, ...beginIAR_Ctrl <= IAR_NOP;<gigantic snip>case state iswhen s0=> NextState <= s0a;-- use this to IPLwhen s0a=> if DiskReady = '0' then-- wait for disk to go not readyNextState<= s0b;elseNextState<= s0a;end if;<gigantic snip>IAR_Ctrl is of type IAR_CtrlType which is:Code:[font=courier]type IAR_CtrlType is (IAR_NOP, IAR_LOAD, IAR_INCR);

author: asmi
author_rank: Super Contributor
timestamp: November 30, 2019, 02:54:19 am
content: Quote from: Bassman59 on November 29, 2019, 11:18:37 pmagain.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 04:29:56 am
content: Is this legit?. This should be 2 clocks connected to a or gate, but each clock line is enabled by their respective conditon.always @ ((posedge data_clk and !silence_inv) or (posedge mcu_clk and silence_inv))

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 05:01:44 am
content: Quote from: lawrence11 on November 30, 2019, 04:29:56 amI don't use Verilog, so I don't know if this is correct.Clock muxes are certainly real. However, switching clocks may produce a short clock which will cause unpredictable results across the fabric. Therefore, you need to be careful with clock switches.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 05:18:24 am
content: I thought this was going to be more simple since I can draw it on a paper quite easily.https://forums.intel.com/s/question/0D50P00003yyG9DSAU/max-10-alternate-between-two-clock-sources-without-reseting-ios-values-?language=en_USBrianHG? You knowledge would surely be useful right now.

author: asmi
author_rank: Super Contributor
timestamp: November 30, 2019, 05:20:04 am
content: Quote from: lawrence11 on November 30, 2019, 04:29:56 amI will have to repeat my advice to take a step back and learn basics. If you would think for a second what kind of gates this code would create, you'd immediately understand that this code makes no sense. I don't even understand what is it you're trying to accomplish here.

author: asmi
author_rank: Super Contributor
timestamp: November 30, 2019, 05:21:43 am
content: Quote from: lawrence11 on November 30, 2019, 05:18:24 amXilinx FPGAs have BUFGMUX primitive exactly for that purpose. As you hopefully understand, this is a HW-specific primitive.

author: asmi
author_rank: Super Contributor
timestamp: November 30, 2019, 05:25:10 am
content: Quote from: NorthGuy on November 30, 2019, 05:01:44 amThey are not created through LUTs. Using LUT output as a clock is a disaster in the making.Quote from: NorthGuy on November 30, 2019, 05:01:44 amXilinx provides special hardware modules to ensure glitch-less switch, which are located next to global clock buffers. I'm sure other vendors do similar things.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 05:26:50 am
content: Quote from: asmi on November 30, 2019, 05:25:10 amIs there a max10 equivalent primitive?I have yet to play around with "primitives".As yu know, I can be a a bit "primitive" sometimes, so this shouldnt be too hard right?

author: asmi
author_rank: Super Contributor
timestamp: November 30, 2019, 05:27:57 am
content: Quote from: lawrence11 on November 30, 2019, 05:26:50 amI don't know - read documentation and find outQuote from: lawrence11 on November 30, 2019, 05:26:50 amPrimitive is a built-in module (in terms of HDL) - meaning you don't need to create an implementation of it. They usually reflect hardware modules found inside FPGA (things like block RAM, DSP, various clock buffers, PCIE IP block, etc.). For Xilinx 7 series, they are all documented in document UG953.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 05:44:31 am
content: thx, it seems like there is exactly what I need.https://www.intel.com/content/www/us/en/programmable/documentation/mcn1395213337540.html#mcn1395926825834clkena primitive

author: hamster_nz
author_rank: Super Contributor
timestamp: November 30, 2019, 05:57:53 am
content: Quote from: lawrence11 on November 30, 2019, 04:29:56 amNot legit. You need to use some FPGA specific resources, that can be discovered by reading this manual:https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/max-10/ug_m10_clkpll.pdfIt is very important to note the caveats over when clocks can switch over - in some use-cases both clocks must be ticking to allow the switchover to occur.

author: emece67
author_rank: Frequent Contributor
timestamp: November 30, 2019, 11:27:56 am
content: .

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 04:59:01 pm
content: Ok well, this looks like debate over system synchronous vs source synchronous.https://www.reddit.com/r/FPGA/comments/bkxyd2/systemsynchronous_vs_sourcesynchronous_interface/?ref=readnextThe data the FPGA receives comes from outside, on 1 pin the clock is external 108mhz, and on another pin its 150 mhz. The data pins are the same they dont move.Both these clock pins are clk_p pins.Calculations done dont need to be deterministic and do not need to be synchronized with other data sets, an output is generated to an external interrupt pin on the mcu.Wich strategy would you take?And, in any case, I still would need to perform the clock switch-over manoeuver, with clkena primitive, correct?

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 05:38:17 pm
content: Quote from: asmi on November 30, 2019, 05:20:04 amIt looks like a MUX selecting one of two clocks. I don't know about newer primitives but ISE and Spartan 3 used to complain about gated clocks. Instead they wanted some kind of enable signal at the component and just one ungated clock.Again, synthesize the thing (for a very limited implementation) and see what the hardware looks like. Both as an RTL view and a Technology view. I'm betting on a MUX which will be implemented in a single LUT. The LUT could implement the circuit with an inverter, two AND gates and an OR gate but that's the thing about LUTs, it isn't always shown how they actually implement anything. It's just a 3 input 1 output black box.The issue is the skew imposed on the gated clock. Neither of these gated clocks are aligned with their original clocks. Sure, it's only picoseconds but it impacts the timing calculations.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 05:59:59 pm
content: Its more than just the circuit. Its the circuit with a choice, a design choice. Do I use a super fast internal clock and sample @ rising edge, or do I let the information"flow at the synchronous-source clock speed".Here is a question I believe, of "determinism", Am I rite? I am "imagining the motor of the FPGA" now but its all in my own mind.A choice of timing clock. For this I have to visualize my needs, and understand the FPGA more in depth, as Asmi said.But I'm sure thee exists condensed format of this informaiton, somewhere on the internetI need to visualize how the data travels, with either source clock or internal clock, to make this choice.

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 07:05:28 pm
content: Quote from: lawrence11 on November 30, 2019, 05:18:24 amOk. When I design for an FPGA, my effort drives me toward a single @posedge clock for the entire FPGA except in sections where it may be really useful. Even then, there are ways around using multiple clocks. Now there is no question that you can place any equation inside the @(posedge/negedge), however, if that logic goes beyond the CLK input gates of the FPGA's logic cell (usually only a 2:1 or 4:1 mux and and gate), what happens is that Quartus will take your equation, feed it's source clocks into normal gates around a logic cell, feed that through an un-clocked logic cell, and use that logic cell's output to drive a CLK wire of the logic cells' clk inputs you write code for inside that 'always @(posedge/negedge)'. You may get away with this for clocking a small few other logic cells in an FPGA design, however, the fabric of the FPGA wasn't designed to do this on a large scale or throughout the chip. The FPGA is best designed to keep everything at 1 or 2 system clocks fed by the PLLs. This is the only way you get a clean synchronous design with very predictable parallel outputs and the highest possible FMAX performance.Now, looking at what you are trying to create, an SPI slave bus interface, is there a way to avoid all asynchronous or combinational logic clocks, use 1 system high speed clock and still meet SPI specifications. Yes. It may even take less logic cells as your results are already operating at you system clock speed. You do not need to buffer between clock domains anymore. There wouldn't be any fancy clocks with async reset lines at all, just the one 'always @(posedge SYSTEMCLOCK) begin'. The SPI reset and enable latch would not just be part of an 'IF()' inside your SPI slave receiver routine. However, operating as a slave, there would be a limit to how fast you may clock your SPI's SCLK compared to your system clock. In such a setup, with this 8:1 (6:1 is still safe) clock limitation, are you actually willing to continue down this road? What this means is if an external master feeding you a SPI SCLK at 10Mhz, I would want my FPGA core SYSTEMCLOCK clock to be at least 60MHz, or in the case of a 1MHz SCLK, I would want a minimum system clock of 6 MHz.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 07:15:57 pm
content: No Brian I am not willing to go down this road.The design has 3 clocks if you count the spi as a clock, that is set in stone.Spi can be slow I dont care, 10mhz is fine.We are getting to the point where the FPGA is not keeping up with my logical abilities with gates, due to these pesky clock issues.It shouldnt be a big deal, I have MAX10 and running the clock pins on the right clk_p pins and clk_n pin for the SPI.mcu clk: clk7_p pinspi clk: clk7_n pindata_clk: clk6_p pin

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 08:29:00 pm
content: Quote from: lawrence11 on November 30, 2019, 07:15:57 pmI'm sorry, but my expertise is using 1 single clock for everything so I need never worry about clock logic.Instead, I personally would treat all the SPI inputs as a function of switching states. It is far simpler to use the 'IF ( spi inputs )' or case ( function (spi inputs) ) including the SPI CLK input as a variable inside the '(...)' instead of having separate clock domains with weird alternate asynchronous switching states and transferring data between these clock domains with that possible issuing timing errors. Any logic I write within those brackets always happens at the edge of my main system clock.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 08:51:15 pm
content: Quote from: asmi on November 30, 2019, 05:25:10 amWhy do you think the HDL code should translate to LUTs? The tools will map the code to the hardware blocks which are the most appropriate (at least they're supposed to).

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 09:09:00 pm
content: Ok, you guys are confusing me now.Lets talk about 2 things, these are the terminologies used in intel's documentation.1:normal mode aka Global system clock2:Source synchronous clocks

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 09:16:51 pm
content: Quote from: NorthGuy on November 30, 2019, 08:51:15 pmAFAICT, all logic is done in LUTs for Xilinx. I don't know that there are any logic blocks consisting of a simple gate or collection of similar gates like a 7400 quad NAND. But I could be very wrong...

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 09:22:17 pm
content: Quote from: lawrence11 on November 30, 2019, 09:09:00 pmGlobal clock is the clock which can reach any part of FPGA. You usually will generate at least one such clock and clock most of your stuff with that clock.Source synchronous clock refers to the clock generated by the same source which sends data to you. And the data being sent is synchronized to this clock. This typically refers to transmissions between different entities on the board.Speaking of SPI, when master sends somehing, its clock is source synchronous. When master receives something, the clock is not source synchronous: the clock is produced by the master, but the data is produced by the slave.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 09:29:02 pm
content: Quote from: rstofer on November 30, 2019, 09:16:51 pmThe logic is done in LUTs, but your HDL can imply different hardware structures as well. Say, if you create an array (or FSM for that matter), it may be synthesized as a BRAM block. If you do multiplication, it may be synthesized as DSP. You can read the Xilinx guidelines which explain how to imply certain elements - there must be some prescribed way for clock muxes as well. You can instantiate things directly (I usually do), but, for some reason, most people would recommend implying things with your HDL.Edit: found a Xilinx write-up for you about this:https://www.xilinx.com/support/documentation/sw_manuals/xilinx10/isehelp/ise_c_imp_instantiation_and_inference.htm

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 09:30:15 pm
content: Yeah I know what it means in terms of signals.I have such things.Parallel data with either a 150mhz clock on a pin, or 108mhz clock on another pin. both clk_p pins. Data pins never change.And spi, wich has its own clock pin of course.

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 09:31:35 pm
content: Quote from: lawrence11 on November 30, 2019, 09:09:00 pm1 & 2 are both the same, if you wire your global system clock to your source's clock. However, in the case of something like SPI's clock, that pin may stop and go at any time. So if you use that clock input as a system clock, everything stops when that clock pin stops.Now, if you have to interface with a device whose bus clock is 4MHz (like a CPU 4MHz clock which is always on), but you wish to run your FPGA logic at 40MHz, you may call the 40MHz your global system clock while that 4 MHz bus clock coming in at one of the inputs, that you would call your 'Source Synchronous Clock'. This does not mean you cannot take that clock input, feed it through the FPGA PLL and get the FPGA to run internally at 40MHz still, but that 4MHz input is what is synchronous to your source. If running your FPGA at 4MHz is fine, then using that clock input direct to your always@(posedge) means your entire FPGA is now running synchronous to your source.

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 09:32:06 pm
content: Quote from: lawrence11 on November 30, 2019, 09:09:00 pmYour design is fundamentally flawed and that's what was being mentioned above. I hesitate to bring it up but I would design the thing as a state machineState 1 : wait for CS* to go high then go to state 2State 2 : wait for CS* to go low then maybe start a transaction timer (to abort hung transactions), set up a bit counter and go to state 3State 3 : wait for the proper edge of the SPI_Clk - DO NOT use edge statements, know what the idle state is supposed to be and transition when the clock comes out of idle. Clock the data bit into the register, decrement the bit counter and goto state 4State 4 : wait for the SPI clk to go idle then goto state 1 if the bit counter is 0 else state 3.In each state check for timeout on the timer and decide how to abort a hung transaction. I would set an error bit and branch to state 1.As long as my system clock was much faster than my SPI clock, the state machine will work. I would still synchronize the CS*, Clock and Data signals when they come into the chip. Details up above somewhere.I didn't diagram the state machine, I certainly didn't code it up and write a test bench so I most certainly do not guarantee it is correct. But it's the way I would approach the problem. There would be one clock, the system clock driving the FSM and no need to clock anything with the SPI clock. Of all the things that scream for a test bench, this is it!I'm sure there are other approaches.Take it as a truism that you can't gate clocks and get reliable logic. Xilinx says so... Or at least they did with ISE.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 09:39:56 pm
content: Quote from: BrianHG on November 30, 2019, 09:31:35 pmI also have a crystal, its an active type ~ 5$ oscillator, theres 25 mhz, 50 mhz, and so on...Thought I didnt have to mention this one.

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 09:47:04 pm
content: Then the question would be, if you take that crystal input, and also drive say your external CPU with the same crystal, that CPU's bus would be synchronous to your design. You can also take that crystal, feed the FPGA, and on an output of the FPGA, have a clock out feeding your CPU which was derived from the crystal's input. If this case, the clock you feed out of you FPGA would be synchronous to the CPU clock.However, even if the frequency is the same, if you have 2 different 50MHz crystal oscillators, 1 tied to your CPU and the other tied to your FPGA. The 2 clocks are no longer synchronous since we cannot guarantee both crystals stay in perfect phase. Now, special measures would need to be taken to ensure that the CPU data bus with it's 50MHz is properly captured in, or transmitted to while your FPGA clock would be operating at a slightly lower or higher frequency.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 09:53:47 pm
content: Cant I just sample my data from the 150 mhz clk6_p pin @ 450 MhzWhen some enable pin activates, sample my data from the 108mhz clk7_p pin @ 324 MhzAnd sample my spi with ~50 mhz clock?I use posedge/nedgede statement to say "hey, this is the perfect time sample", edge is right smack in the middle of data timing. So I am sorry if this is causing confusion.

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 10:07:44 pm
content: Quote from: lawrence11 on November 30, 2019, 09:53:47 pmYes, you can sample serial or parallel data such data at such speeds with ease, ie 150MHz and 108MHz with ease. 450MHz and 324MHz is a little more worrying... SPI at 10MHz is so slow, you can use any system clock at 50MHz and above to read that SCLK and MOSI as if it were just normal input pins while your serial decoding logic basically can wrap cycles around it in speed. The Intel FPGA does support multiple parallel clocks and it's memory cores allows you to read and write from 2 different clock domains simultaneously with ease. This means one side on these dual port rams may operate on the 150MHz input bus clock. That side of the ram is 'synchronous clocked' to the data input bus. The other side of your dual port ram may be clocked by your 50MHz clock, of if you are using the PLL, any multiple of that clock to perform internal mathematical functions. This does not mean you cannot use that 150MHz clock to run you FPGA logic functions as a synchronous design. It is up to you the developer.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 10:34:44 pm
content: I dont have data coming @ 450 nor 324 Mhz.I was proposing internal clock speeds. Wich should be derived from the crystal clock, PLLed

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 11:01:48 pm
content: Quote from: NorthGuy on November 30, 2019, 09:29:02 pmCertainly! I can declare an array for main memory and it will PROBABLY be put in BlockRAM but it could be put in LUTs (where the D-flops are located). Or, I can instantiate a BlockRAM and guarantee it is going to be placed in BlockRAM.

author: lawrence11
author_rank: Frequent Contributor
timestamp: November 30, 2019, 11:09:59 pm
content: Isnt it a default to have an active clock like I showed you?Brian you seem to have changed your proposal.Seriously, were you guys thinking I was gonna use SPI as a system clock and didnt have such a clock?

author: rstofer
author_rank: Super Contributor
timestamp: November 30, 2019, 11:22:03 pm
content: I would think that clock speeds above 100 MHz (and maybe even 50 MHz) would be an advanced topic. Anything in the 400+ MHz range is certainly going to require great care in logic design to meet timing. Pipelining comes to mind. Again, just because it simulates doesn't mean it will synthesize. Pay attention to the timing report. Unless you are dealing with a very high dollar chip, I would not expect timing closure much over 100 MHz.My little LC3 project will run at 100 MHz on an Artix 7 100T but timing fails at 200 MHz. I didn't iterate over values to find the highest possible frequency because the crystal oscillator is 100 MHz and that is as fast as I want to push the design. In ISE they used to tell you the maximum possible frequency. I haven't found that datapoint in Vivado. I'm sure it's there somewhere but I haven't run across it.

author: BrianHG
author_rank: Super Contributor
timestamp: November 30, 2019, 11:46:13 pm
content: Quote from: lawrence11 on November 30, 2019, 10:34:44 pmI focused on SPI since you started this thread with a SPI receiver. SPI is a special case as it's clock can stop and go, and, sometimes, you may want to reset logic not based on the SPI clock, but an asynchronous event with the SPI input pins.I am assuming that your 108 and 150 MHz clocks are a normal standard bus where you don't begin resetting you internal logic on these weird occasions, when the clock is going low instead of the normal latching high, or the clock stops and other control signals take over to command your system functions, right?As for your system FPGA clock, you will run into a maximum capability reported by Quartus depending on how you describe logic and functions in your Verilog code. Since what HDL is describing is a set of wires connected together through gates which perform your equations feeding a set of flipflops' 'D' inputs while their 'Q' output switches/latches those input's results at the next clock, a really complex set of logic gates between the 'Q' output results feeding the next stage 'D' flipflops inputs may lower this maximum possible clock rate, otherwise, the late arriving latched data will give you errors.In my RS232 debugger thread, on the cheapest FPGA, the RS232 UART can easily run above 200MHz. However, the debugger itself was written for simplicity of function and ease of reading the code. On the same bottom end FPGA, it can operate just above 125MHz max. Now, I can modify it to perform at 200MHz, but, reading the code, many would ask why did I latch and compare some fundamental functions along 2 stages with latched registers, making the simple code look like it perceived or processed time along a skew. This would be a deliberate necessary step if I wanted that code, with the same structure and commands to perform above 200MHz like the RS232 UART is capable of.If your top data clock is 150MHz and you want to do some processing of that data in real time, the Max10 can handle that with ease and you have some breathing room. Getting a processing design to run in the 250MHz on the slowest available Max10 would take some work as this is the clock limit of the internal dual-port memory blocks. Looking at the '-C8' version data sheet, the slowest function you have is the 18x18bit multiplier. Running that multiplier in single stage clock mode, this means your 2 input's multiplied results are ready by the next clock cycle is 160MHz in single power supply mode, 190MHz in dual power supply mode. I would use this 160MHz as your worst case scenario, so, 150MHz on one of you data buses, as a target system clock frequency is a good fit. Depending on what you are doing, if you have some sophisticated math or rules, you may have to learn how to pipeline your design to maintain this 150MHz performance.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 30, 2019, 11:59:32 pm
content: Quote from: lawrence11 on November 30, 2019, 09:30:15 pmYou can create one block which handles one set of data, and the other block which handles the other set. You can route the data to both blocks.The speed of their clock doesn't matter, as long as it is not too fast for you.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 12:11:58 am
content: Quote from: rstofer on November 30, 2019, 11:22:03 pmThey removed the feature in Vivado:https://www.xilinx.com/support/answers/57304.htmlI find it kind of funny that with a bloody computer, and soooooo much on screen data and tables to show you everything that you have to read that thread, and use the formula given to you in that thread to calculate the FMAX on your own. Where the formula is ' 1/(T-WNS) ' and T is your given clock period. Though, on their timing reports video:https://www.xilinx.com/video/hardware/timing-summary-report.htmlThey pretty much have an use all the same terminology and data timing points as Quartus' timing report, yet the 1 single number figure they want you to calculate by hand with a calculator is the FMAX? I just want an Idea of how much work I need to do to stretch my design or it's expand-ability at a glance before digging into the difficult numbers.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 12:24:28 am
content: Please be more clear when you say, "you can create a block"?Something like this? The calculation in question is comparing the magnitude of 2 bytes, with an upper and lower value. I just wanna make sure the same logic is re-used and the sampled clock just de-selected, switched and not some whole new logic re-created, lets be efficient here.always @(posedge clk_1)beginif(enable==1'b0) begincalculation....endendalways @(posedge clk_2)beginif(enable==1'b1) begincalculation....endend

author: NorthGuy
author_rank: Super Contributor
timestamp: December 01, 2019, 12:26:19 am
content: Quote from: BrianHG on December 01, 2019, 12:11:58 amA lot. The tools stop optimizing as soon as the timing is met. If you want higher speed, the tools may be able to make it, but at the cost of extra optimization, which may take hours. There's no way to find out aside of actually trying.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 12:50:08 am
content: Quote from: lawrence11 on December 01, 2019, 12:24:28 amRunning at the upper limits of the FPGA means you will not be able to use the same logic with 2 different clocks simultaneously. Since we don't know what you are trying to do, but based on your post, I'm thinking something closer to this:----------------------------------------------------always @(posedge clk_1)beginif(enable==1'b0) beginif ( input_data > low_limit && input_data < high_limit ) input_data_in_range <= 1;else input_data_in_range <= 0;....endend-------------------------------------------------------The above test only takes 1 logic cell. That 1 logic cell is the 'input_data_in_range' result. The math involved inside the if's (...) are the gates preceding the 'D' input of the logic cell register ''input_data_in_range'. Now, if your input data is 8bits and the high_ and low_limits are also stored registers 8 bits each, this logic will be 25 logic cells total.Now, if you add more tests, on the 'input_data', those 8 bits are automatically reused, or, if you use the high_ and low_limits elsewhere but with different data, then those 16 logic cell registers again are automatically re-used and just the alternate new 8 bit input data will add 8 additional registers to your design. IE, expand the above to 1 upper and lower limit, 16 logic cells, 2 different 8 bit input_data making another 16 logic cells, and 2 different data_in_range outputs #1 and #2 regs would bring the design to 34 logic cells. You are using nothing of the bottom end Max10's 2000 logic cells here. What else do you need to do?

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 12:59:01 am
content: Yeah something like that Brian.the "calculation" , should this be defined as a function? For the "compiler" to understand I wanna re-use this, if the upper and lower limits are the same for both.Or is it gonna be smart and re-use what it can?

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 01:06:37 am
content: Well I did not know my pre-requesites.Max10 seemed like the best since it was 3.3 Volts.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 01:19:29 am
content: Quote from: lawrence11 on December 01, 2019, 12:59:01 amSince I don't know the speed you need to run the 'Function', I cant tell you. If the function only needs to run at 50 million times a second for each data input, IE a kind of DSP processor, to save space, the general practice would be to run the function at 100MHz or 150MHz, 1 clock, all positive. What you then do is take the slower source data A & B coming in to feed through the function multiplexed one after the other as 1 single pipe which feeds the function. At the output of the function, you de-mux your results back into the results A & B. In fact, int this setup, if your source data is 50MHz and you run your DSP function at 150MHz, you can feed it muxed 3 source data's and de-mux the output in 3 parallel answers. 1 calculating DSP pipe running 3x the speed of your source data means you can calculate 3 different products simultaneously. This is how one port of the FPGA memory inside the 'FPGA VGA Controller for 8-bit computer' project was made into a 5 port ram where the read addresses were running at 1/5th the system clock rate.Going the other way is a problem. If you want to parallel calculate a 108MHz data simultaneously with a 150MHz data, you would need a 300MHz DSP core, or just 2 DSP cores running in parallel. However, if you only need to do 1 data port at a time, 108MHz, or 150Mhz, you can just keep the DSP running at 150MHz and switch between source data. Converting an 8bit 108MHz data to 150MHz with a 'data_ready' signal would only take 18 logic cells for reliable functionality, 30 logic cells for guaranteed under obscene circumstances (Such circumstances being an unstable glitchy source clock).

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 01:23:38 am
content: its not simultaneously but mutually exclusive.Worst case stress test would be 150mhz.All logic blocks do the exact same frikkin thing, its just a different pin, and a bit slower.You wanna know why this pin is there? Layout reasons ok! Things got...messy.Both pins of the type clk#_pMy original question was regarding the syntax, and now I am just confused.Why did you guys ever think I didnt have a crystal? I aint that noob.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 01:25:01 am
content: Without knowing you function, for all I know, it may only take 100 or 200 logic cells. You may still be using nothing of the Max10. Heck, the 8bit video card project is only at 600 logic cells now, that's with RS232 debugger com port, cursor lines, video generator, plus 8kbyte ram for font and test memory. It would only take around 30% of the logic cells in the Max10 and it is almost finished.

author: rstofer
author_rank: Super Contributor
timestamp: December 01, 2019, 01:27:57 am
content: Quote from: BrianHG on December 01, 2019, 12:11:58 amThanks for the tip! My little LC3 will only run about 104 MHz according to the calculation. 100 MHz is probably close enough because I don't want to get into lengthy optimizations. I certainly don't want to pipeline the design for a toy project.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 01:34:54 am
content: Sometimes Its impossible to communicate via this forum.The time wasted today was humongous.I need to talk to a tutor real time.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 01:41:17 am
content: Quote from: lawrence11 on December 01, 2019, 01:23:38 amSomething like:always @(posedge clk150) beginif (source_a_or_b == 1) begindsp_input_data <= source150_data;dsp_input_data_rdy <= source150_data_rdy;end else begindsp_input_data <= source108_data;dsp_input_data_rdy <= source108_data_rdy;enddsp_output <= (dsp_input_data * 10 / 3 + 100 + offset_reg_setting) * contrast_reg_setting;dsp_output_rdy <= dsp_input_data_rdy;end // always clk150mThe first IF() selects what the reg 'dsp_input_data' will be equal to based on the input ' source_a_or_b ' being high or low. It also makes the 'dsp_input_data_rdy' reg equal to the correct matching source data ready flag.After the IF(), ELSE, the next line is the DSP and the next line after that passes the data ready flag through the same number of clock steps required by the dsp.You now have switch selected 2 alternate source data for the DSP processor. The only thing you are missing is the clock domain transition step between the 108MHz and 150MHz clock.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 01:45:01 am
content: So these calculations are considered DSP and not flip flop or gates?Sweet deal!

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 01:56:46 am
content: Quote from: lawrence11 on December 01, 2019, 01:45:01 amThe 'dsp_input_data' would count as 8 logic cells as it is a register. Same for the ' dsp_input_data_rdy ' would count as 1 since it is 1 single signal wire.if your 'dsp_output' is 16 bits, then that counts at 16 logic cells and the ' dsp_output_rdy' still counts as 1 since is it 1 wire signal cell.This here ' (dsp_input_data * 10 / 3 + 100 + offset_reg_setting) * contrast_reg_setting; ' is a hefty calculation which is created out of gates and a dedicated multiplier or 2, but the final result will be the 16 main logic cells. However, this may be too hefty for 150MHz operation. You may need to break it into 2 or 3 steps. With a 16 bit result, each step will eat another 16 logic cells unless the compiler can find ways to achieve the same results while removing unnecessary logic cells which happens all the time. The numbers I am giving you are worst case scenario.So, if your function is only 10 times more complicated that what I created above, your DSP will eat only around 170 logic cells, plus maybe a few dedicated 9x9 or 18x18 multipliers. You still haven't scratched 10% of the smallest MAX10, and only 0% of it's embedded memory. If you exceed the dedicated multipliers of the MAX10, then those additional parallel multiplications will be achieved in gates. Addition and subtraction is usually done in gates unless tied to 1 multiplication where the addition may be added into part of the dedicated multiplier logic known as a MAD, or multiply add as these standard DSP functions are industry known for digital filters.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 01, 2019, 02:01:31 am
content: its not 16 bit, its 2 byte, seperate byte.Should be good @ 150mhz

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 02:23:18 am
content: The bottom end max10 has 16 18x18bit multipliers. So at 18 bit if you:p3 <= p1 * p2 ;p6 <= p4 * p5 ;p9 <= p7 * p8 ;p12 <= p10 * p11 ;p13 <= p3 * p6 ;p14 <= p9 * p12 ;final_result <= p13 * p14 ;You would eat 7 multipliers, 126 logic cells with a clock delay from inputs p1,p2,p4,p5,p7,p8,p10,p11 to output final result would be a 3 clock pipe. This code would be doing 1 billion multiplies a second with a 150MHz source clock.I am not counting where the source logic cells where the p1,p2,p4,p5,p7,p8,p10,p11 are stored. If they are all 8 bit, that would be 64 logic cells.To think that a sub 10$ chip can do anything a billion time a second and still be relatively empty and have room to do quite a bit more is kid of amazing yet there is so much more larger and faster out there.

author: asmi
author_rank: Super Contributor
timestamp: December 01, 2019, 03:16:12 am
content: Quote from: NorthGuy on December 01, 2019, 12:26:19 amAnd to me that behavior makes perfect sense, especially if you consider that they have to support parts with insane amount of resources, so finding the absolute best solution can take ridiculously long time, and in most cases when you have a well-constrained design, you don't really need the absolute best.

author: BrianHG
author_rank: Super Contributor
timestamp: December 01, 2019, 03:30:18 am
content: Quote from: asmi on December 01, 2019, 03:16:12 amAre you sure that's true. I have an old design which takes 90% of an EP3C40, and to meet my designated FMAX, it took 7 hours to 'fit'. (Compile only around 10 minutes.). Now, compiling that design into an EP3C80, at 45% full took around 30 minutes to 'fit' reaching my designated FMAX. When a FPGA is almost empty, the fitter can always take the most optimum route, including duplicating registers at different locations to achieve the final FMAX, IE, a straight line. There is no thinking to be done. Insane resources means easy routing in a straight line. On the other hand, when the FPGA is full as it lacks resources, you don't have the luxury of routing in these straight lines. Your fitter must work 100 fold harder to achieve both a fit and push things around that maze of FPGA fabric to get that timing as good as possible.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 01, 2019, 03:43:06 am
content: Quote from: lawrence11 on December 01, 2019, 01:23:38 amRe-using processing logic only makes sense if it's massive. Otherwise you risk spending more resources on re-using then you gain.Look at the docs for your FPGA and see what it can offer for clock muxing. If it has clock muxes, see if you can use them.If you cannot mux, there are things as run-time reconfiguration - where you reconfigure parts of FPGA on the fly - but these techniques are complex and slow to switch.Most likely you can mux clocks with regular LUTs, but this will introduce really big jitter, and may also introduce glitches. It may work at 150 MHz though. Just try it and see if it meets timing.You can also detect the transitions of your clocks using higher frequency sampling. However, for 150 MHz, you will need really high frequency. For example, Xilinx 7-series have oversample mode - you can sample at x4 the clock, which is about 2.4 GHz for its maximum 600 MHz clock frequency. This is enough to detect transitions in your 150 MHz clock.The straightforward way is to simply sample the signals separately, then cross the clock domain to your global clock (at around 200 MHz) and then use mux to select the sample you want. This way you can re-use your processing chain.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 01, 2019, 04:12:29 am
content: Quote from: BrianHG on December 01, 2019, 03:30:18 amP&R is a very complex task. The lack of resources is one of the factors. The speed is another.For 50 MHz you can place your elements practically anywhere. If you want to run it at 500 MHz, you must place all destinations within few connection boxes from their sources, which creates placement problems and local congestion. If you have a big design, it's much easier to findaacceptable solution, than the solution which can run at the highest speed. So, why bother with high speed if you don't need it anyway. That's what Vivado does and that's why it doesn't tell you the highest achievable speed.Sometimes slack numbers will give you the idea of the speed you can achieve. Other times they will be way off.

author: rstofer
author_rank: Super Contributor
timestamp: December 01, 2019, 03:16:36 pm
content: Maybe I have missed it in Vivado but ISE used to point out the longest logic chain. You would swear the logic wasn't very complex yet there were 19 levels of logic between clocks. It was embarrassing!If you drilled down far enough, you could see the levels in the RTL Schematic.For my toy projects timing hasn't been an issue. But this may be another number that is worth tracking.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 08:34:45 pm
content: So, how is a main system clock supposed to be generated, am I doing this right?To sample a 150mhz clock I need something 3x, so 450mhzI was just wondering what the Instantiation was for, I thought instantiations were for testbenches?ALTCTKCTRL gave me 2 files that I can play with, the rest to me is all to be ignored and chinese.So for anything that has a relation with the switchover should be found in ALTPLL, not ALTCLKCTRL, correct?

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2019, 09:47:12 pm
content: Quote from: lawrence11 on December 03, 2019, 08:34:45 pmTo sample 150MHz, you need a 150MHz clock. Unless there is something special about your sampler's data buss.Is the MAX10 'PLL' providing a clock for your sampler?Or does the sampler generate it's own clock?How many bits is the buss?

author: rstofer
author_rank: Super Contributor
timestamp: December 03, 2019, 10:07:37 pm
content: Earlier I mentioned that you can't find an edge by usingif pos_edge(mysignal)inside analways @ (posedge clk)because the clk edge won't coincide with the transition on mysignal. What you do is keep a delayed copy of mysignal (what it was before the current clk event) and use a bit of logic to see that there is a difference between the current value and the previous value.Like this:https://www.chipverify.com/verilog/verilog-positive-edge-detector

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 10:25:11 pm
content: Ok then, I will pick that route, 150mhz sample @ 150mhz clock, source synchronous mode.This not being the normal mode, but source synchronous mode.Wich will have more delay but more power efficient.I will have to get familiar with a clock switchover, now that I am more familiar with this GUI.Still, it lacks videos that shows these file organizations, like STM32, nice videos everywhere.They should show: Heres how it works a sim/synthesis workflow with whatever library GUI we offer.

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2019, 10:27:44 pm
content: Quote from: rstofer on December 03, 2019, 10:07:37 pmThis wont work, for example, if his core clock is 150MHz and the sampler's clock is 148.5MHz. I have a nice small clock domain code which works great for slight clock inconsistencies.For sampling his SPI clock, your mentione 1-delay system exactly the way he can extract the SPI SCLK transition and perform a bit transaction at every low-high and high-low transition.It is exactly how my RS232 Sync UART example detects the start bit and aligns it's internal period counter.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 10:37:35 pm
content: Its like the NAND land video.You choose your gears.The max10 has a max gear of 450 mhz, wich is result of PLL via precision crystal.But you can setup the stuff to work with other slower gears. Wich I will do, I see now...= determinism, less power, connect the chain to chosen clock.But if you want the absolute fastest propagation delay, you can run as fast as possible, 450 Mhz. Connect the chain to PLLed system clock.At the highest speed, FPGA will sample once reference is high, process @ 450mhz.Do I get it guys?

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2019, 10:42:18 pm
content: Quote from: lawrence11 on December 03, 2019, 10:25:11 pmHow do you figure more delay. If your sampler is 150MHz, and you FPGA is computing at 1:1 speed, and you still need all your data to compute an answer?You are talking a difference of maybe 2/150000000 of a second in difference as you still need to wait for that last sample to come in.Unless you are not computing in real time, or not computing in parallel. The 1 thing which makes using an FPGA over a MCU/CPU, the entire reason for going to such a complicated design for that raw 0 wait speed capabilities.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 11:02:19 pm
content: So it would be totally stupid, unheard of even, to run an FPGA @ 450mhz when you fastest signal is clocked @ 150mhz from source synchronous, and its source synchronous everywhere.So I never needed a 5$ crystal?

author: NorthGuy
author_rank: Super Contributor
timestamp: December 03, 2019, 11:06:18 pm
content: Quote from: lawrence11 on December 03, 2019, 10:37:35 pmYou just take the source clock in and use it for sampling and some logic until you cross to your own clock domain.Or, if the clock frequency is slow, you sample both the source clock and data with your own clock at much higher (10x+) frequency, detect transitions in the source clock and use the data samples which were taken during the transition.

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2019, 11:09:36 pm
content: Quote from: lawrence11 on December 03, 2019, 11:02:19 pmNo. If you have room for only 1 multiplier in your design, and you need to do 3 unique different multiplies to be performed on every sample, and you don't want to fall behind, yes, running that 1 multiplier at 3x the sample speed would make sense.The advantage of a single crystal is running you core at 1 clock speed while everything else coming in may be operating at lower clock frequencies. This means no clock switching necessary. If you have inputs operating at lower sample speeds, just the input itself is clocked at that speed, then that data is passed to you main unified FPGA clock speed. So long as your core is running a few hundred hertz faster than any sampler data input clock, you are safe to go about things this way.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 03, 2019, 11:12:08 pm
content: Quote from: lawrence11 on December 03, 2019, 11:02:19 pm450 MHz is too slow to sample 150 MHz signal. Your only choice is to sample with the source clock.Your FPGA does need an internal clock. It better not be related to the input - because otherwise if the input clock stops, FPGA stops too.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 11:18:33 pm
content: Quote from: NorthGuy on December 03, 2019, 11:12:08 pmWell In my case that is possible.It will simply be in standby untill the next edge, wich will save power, come to think of it.Is the rule x4600mhz would be necessary to sample a "reference clock" of 150mhz."Reference clock" and "gear connection".A "gear connection" is a posedge, a sample is an If, correct?

author: BrianHG
author_rank: Super Contributor
timestamp: December 03, 2019, 11:33:40 pm
content: Why do you want to sample the edge clk of your sampling clock?

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 11:51:50 pm
content: Quote from: BrianHG on December 03, 2019, 11:33:40 pmYou cant sample the edge of a sampling clock of 150mhz.You must use the sampling clock as a gear connection, and let it run the logic chain.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 03, 2019, 11:56:46 pm
content: Quote from: BrianHG on December 03, 2019, 11:33:40 pmLooks like he has several clocks on different pins which he wants to use at different times to sample the same data lines, and he doesn't have (or doesn't know how to use) the clock mux.One of the methods is to treat the clock as data (same as if you wound want to read 200 kHz SPI), but 150 MHz is too fast for this.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 03, 2019, 11:59:49 pm
content: Not only I dont know how to use the mux, I dont know to how to setup the IP's offered by Intel and how to stay wihin an easy simulation/synth workflow.I contacted Intel and explained the horrendous lack of direction in their online tutorials.I need the clock mux only between the 108mhz and 150 mhz clock.The SPI is a seperate entity.

author: rstofer
author_rank: Super Contributor
timestamp: December 04, 2019, 12:01:53 am
content: Quote from: BrianHG on December 03, 2019, 10:27:44 pmWhich is exactly where I have used it.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 12:07:13 am
content: Quote from: lawrence11 on December 03, 2019, 11:59:49 pmI'm still not sure about what you are trying to do...to me, this is a AB selection mux:Code:input wire sys_clk;input wire [7:0] data_a, data_b;input wire data_a_rdy, data_b_rdy, select_ab;output reg [7:0] data_mux_out;output reg data_mux_out_rdy;always @(posedge sys_clk) beginif (~select_ab) begindata_mux_out <= data_a;data_mux_out_rdy <= data_a_rdy;end else begindata_mux_out <= data_b;data_mux_out_rdy <= data_b_rdy;endendI would have just converted the source 150 and 108Mhz data streams to my fixed local crystal 150MHz.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 12:09:26 am
content: Quote from: BrianHG on December 04, 2019, 12:07:13 amNo, this is not a good mux, this is the kind of mux you would use on a slow signal with normal mode selection.We want source synchronous clocking.Mux is a hardware primitive that you have to setup with GUI then call somehow, it will create a module and ports, I think.The it will act like a gear switcher and it wont bug when you use their IP catalog stuff.From the ALTPLL ip catalog.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 12:11:51 am
content: Why are you switching the PLL to a sampling clock if the samplers are providing you a reference sampling clock.I would have just converted the source 150 and 108Mhz data streams to my fixed local crystal 150MHz and still use my AB switch code.It is different if you need to generate the 150MHz and 108MHz clock, well, not quite as you can program your PLL to create 2 clock outputs at 2 different frequencies.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 12:19:11 am
content: Quote from: BrianHG on December 04, 2019, 12:11:51 amSo a 150mhz clock, system clock, that never goes away, is the all around solution.such a 150mhz clock, would have to be derived from a crystal.The system clock of 150mhz + a few hundred hz will sample a 150mhz that is not persistent, and totally out of phase with the system clock?I see now. So we can sample 150mhz clock with 150mhz + a few thousand hz, thus avoiding all that clock switchover stuff.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 12:23:09 am
content: Quote from: lawrence11 on December 04, 2019, 12:19:11 amYes, if your samplers has their own clocks, or you use a PLL to make their clocks, you can convert those samples to you 155MHz clock domain with a 'data_enable' which will pulse high and low as each new sample is ready. So, with 150MHz system clock and a 75MHz sample clock, that enable will go high and low every second system clock. Your 'gear' control for your logic.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 12:26:03 am
content: Quote from: BrianHG on December 04, 2019, 12:23:09 amThey do have their own clock, its SPI data and synchronous data, there is a signal that rises or falls right smack in the middle of this data. Only the fast data will have a switch, from 150 to 108.Yeah but you proposed that same solution last time, then you mentionned the Bus of 150mhz should be in phase with the derived PLL of 150mhz. I then told you tis was not possible.

author: NorthGuy
author_rank: Super Contributor
timestamp: December 04, 2019, 12:40:30 am
content: There are many ways for clock domain crossing.For example, Xilinx has asynchronous FIFOs - you write it with one clock and read it with a different clock. So you write with 150 MHz clock and read with 200 MHz internal clock.Another FIFO, you write with 108 MHz clock and read with the same 200 MHz internal clock.All you need to do is select the correct FIFO.Altera should have something similar.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 12:46:14 am
content: Quote from: NorthGuy on December 04, 2019, 12:40:30 amFIFO is overkill, but simple as the FPGA vendors push them that way to show off asynchronous clocking dual port rams.You just need 4 registers on a source clock, and 4:1 MUX on the out side operating 2 clocks behind the sampling 4 registers.And if you were able to operate at 1:1 frequency, then using this technique, you system clock can realistically only need to be 1MHz faster than your sample clock.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 01:09:34 am
content: Quote from: BrianHG on December 04, 2019, 12:23:09 amWhat do you mean by "samplers", are you talking about a pin, aka CLKx_p or n, or are you talking about series or parallel data that has a rising(or falling) ege right smack in the middle of this data, aka a clock (sampler).Well whatever the case, rest assured, all 3 clocks coincide with their respective CLKx_p or n pin.Even my XXMhz crytal corresponds to CLK0_p.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 01:15:46 am
content: If you have a CLK input pin for the sampler, then that sampler has it's own clock.For example, I have a HDMI receiver IC. It send me a clock with the data. It feeds an input on my FPGA so it generates it's own clock.If you have an 'output pin' seeding a clock to the sampler, then your FPGA is generating the sampling clock.For example, I have an audio ADC connected to my FPGA. It requires a clock signal. Within my FPGA, I create that 96KHz clock by dividing my main system clock from the PLL and drive the audio ADC's clock input.You may also have another external crystal oscillator dedicated to feeding your ADC and FPGA input.

author: BrianHG
author_rank: Super Contributor
timestamp: December 04, 2019, 01:39:20 am
content: Quote from: lawrence11 on December 04, 2019, 01:09:34 amI'm sorry, we assumed that the 108MHz data and 150MHz data came from an AD sampler just by some of the previous language being used. Ok, lets just call it a parallel data port with it's own clock coming in.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 03:17:59 am
content: Ok yeah, I am not sampling 150mhz sinewave with ADC's.Sampling meant, registering the value of the parallel dataset at the sampling time, aka edge of a clock.Dont get mixed up, my FPGA has no ADC's.The CLK has its own sampler, or the sampler has its own CLK, however you wanna put it.Anyways, I have to pat myself on the back some more, that was some incredible foresight to associate CLK pins with clocks.

author: lawrence11
author_rank: Frequent Contributor
timestamp: December 04, 2019, 03:52:00 am
content: Yeah I gotta hand it to us Canadians, we smart.Also those from New Zealand.Basically the whole Commonwealth, we smart...Am I forgetting anybody?