Yay, Chip's xoroshiro128 PRNG Verilog is working in my DE-0 Nano!
I have 8 blinky green LEDs twinkling at random.
What a struggle. 10 hours from idea to blinky. What with the Altera/Intel web site suffering maintenance this morning, the long winded registration, monster down load and install. Then WTF is all this? Quartus is huge and complicated (and slow). Seems to have a billion options that one does not know if one needs or not. Then getting the top level module sorted out and the pin assignments. Then WTF is the USB blaster? Another monster download....
Grrr...
Anyway something works. Except I also directed an instance of the PRNG to some GPIO pins but I can't see any action there on the scope at all. Pin assignments have been checked and checked...
Here is the top level module. I renamed Chip's rnd to xoroshiro128plus.
//
// blinky
//
// DE0-Nano pin outs.
// Signal Name FPGA Pin No. Description I/O Standard
// CLOCK_50 R8
// Signal Name FPGA Pin No. Description I/O Standard
// KEY[0] PIN_J15 Push-button[0] 3.3V
// KEY[1] PIN_E1 Push-button[1] 3.3V
// Signal Name FPGA Pin No. Description I/O Standard
// LED[0] PIN_A15 LED Green[0] 3.3V
// LED[1] PIN_A13 LED Green[1] 3.3V
// LED[2] PIN_B13 LED Green[2] 3.3V
// LED[3] PIN_A11 LED Green[3] 3.3V
// LED[4] PIN_D1 LED Green[4] 3.3V
// LED[5] PIN_F3 LED Green[5] 3.3V
// LED[6] PIN_B1 LED Green[6] 3.3V
// LED[7] PIN_L3 LED Green[7] 3.3V
// Signal Name FPGA Pin No. Description I/O Standard
// GPIO_10 PIN_B6 GPIO JP2, 2
// GPIO_11 PIN_A6 GPIO JP2, 4
// GPIO_13 PIN_D6 GPIO JP2, 6
// GPIO_15 PIN_C6 GPIO JP2, 8
// Make a slow clock from a fast one
module SlowIt (input FastClock, output reg SlowClock);
reg [25:0]R;
always @(posedge FastClock)
begin
R = R + 1;
SlowClock = R[22]; //(50*10^6)/(2^24) or 19.15 Hz
end
endmodule
// The classic "Hello world" of hardware.
// Only this time using the xoroshiro128+ PRNG to drive 8 LEDs.
module blinky (input CLOCK_50, input reset_btn, output[7:0] LED, output[3:0] GPIO);
// Slow down the clock
wire slowClock;
SlowIt(.FastClock(CLOCK_50), .SlowClock(slowClock)); // Implicit instantiation
// Random flashing of green LEDs.
xoroshiro128plus r1 (.resn(reset_btn), .clk(slowClock), .out(LED));
// Full speed random wiggle of 4 GPIO pins
xoroshiro128plus r2 (.resn(reset_btn), .clk(CLOCK_50), .out(GPIO));
endmodule
Now I need to put the bit shuffling in and figure out how to make a UART to pump the random bits out of there as fast as possible.
Now I need to put the bit shuffling in and figure out how to make a UART to pump the random bits out of there as fast as possible.
If you have a FT232H/FT2232H they can pump up to 12MBd streams.
FS USB Uarts are more modest, better ones can manage 3~4Mbd one way, best in class can do ~ 9Mbd effective rates,
Just a DE0 Nano and a USB cable for the USB Blaster.
I do have a Parallax "DE0-NANO PROP2 EMULATOR" expansion board and a Prop Plug to connect to it. Not in use at the moment.
I have no idea what speed the Prop Plug can achieve.
Even so, at the max speed of a USB interface I think we end up getting those random bits much slower than a C code version running on the PC.
I should look into the Verilator Verilog to C++ compiler, it did not work out of the box for me.
On the other hand...I'm getting into this idea of generating logic for an actual FPGA.
Anyone, have any idea why I cannot get output on the DE0-Nano GPIO pins ?
I designed an entire simple CPU once that ran pretty well under emulation. When I tried synthesizing it the Verilog compiler deleted all of the logic because none of it was connected to any of the pins. :-) One of these days I intend to get back to it. Of course, that was many years ago and I never seem to find the time...
What? David, you mean just now I'm doing better than you did? How can that be?
Actually, I was totally stunned when the 8 green LEDs started blinking at random the first time I loaded it!
I have no idea where my GPIO output has gone.
There is a ton of warnings in the build output that give no clue as to what may be wrong.
For example:
Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details
Hmm...Sounds like a likely problem. What "I/O Assignment Warnings report"?. Where?
I'm not surprised you're doing better than I did. I did do some playing around with numerically controlled oscillators a while back and those seemed to work. I'm sure I could have gotten the CPU to work but I needed to figure out how to hook it up to the internal RAM blocks and I/O pins and I got distracted by this new fangled processor called the Propeller. The rest is history. Maybe I should get back to it. What does your Verilog look like?
10 years ago or so I started messing with VHDL. I cooked up a brilliant VHDL version of a 3-way loudspeaker crossover circuit. From an analog opamp design. It simulated fantastically under GHDL. Frequency response exactly as planned. It was doomed because most of it was not synthesizable into an FPGA. I wish these simulators would tell you what is real and what is not. A friend of mine adapted the code into a plugin for some Windows audio processing software in Java or whatever and said it sounded great!
My not working Verilog produces messages like the following when I build it:
Warning (12241): 2 hierarchies have connectivity warnings - see the Connectivity Checks report folder
Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details
OK, sounds like connections are wrong.
But what "Connectivity Checks report folder" and what " I/O Assignment Warnings report"?
Where? How?
Maybe I'm just getting too tired after 17 hours fighting with this. A Google search or a dozen turns up nothing.
I don't know that any pins work except the ones driving the LEDs.
So I swapped the high speed and low speed PRNG outputs around.
The result was the LEDs were lit up all the time. As expected as the random bits are hitting them at 50MHz.
The GPIO did not move!
I think what I need is the DE0-Nano pin assignment file. Which I cannot find anywhere. I guess it's on the CD that came with the board. If I ever had that.
Or I assign all the GPIO pins manually and see if I can drive any of them!
After 20 hours at this I think I'm about to pass out...
I've discovered things aren't stable on the Ryzen setup. It seemed okay until I was hammering it ... I discovered I also can't even reliably download a newer iso using the Ryzen - md5sum failed its check.
I've had some of my own success now. The Ryzen is behaving now that I've disabled a number of options in the BIOS. Just have to narrow it down but my top bet is something about the dynamic clocking is suspect. I'm even starting to think it may be a hard bug in all current Ryzens that can't be fixed without a revision.
I don't know about "flow". Working with Quartus feels like trying to wade through some non newtonian fluid just now. This is only a tiny bit of Verilog and it takes an age to synthesize. How long does it take to build a working P2? How often do you do that? I guess the question is what is your work flow when tweaking the P2 code?
If nothing else this little experiment makes me appriciate how much effort you have put into the P2!
Do you mind if I put this up on github? With an MIT license say?
Aside: I'm amazed this cheap Rigol scope, hacked from 50MHz to 100Mhz bandwidth, can display reasonably square bits flipping at 50MHz.
I don't know about "flow". Working with Quartus feels like trying to wade through some non newtonian fluid just now. This is only a tiny bit of Verilog and it takes an age to synthesize. How long does it take to build a working P2? How often do you do that? I guess the question is what is your work flow when tweaking the P2 code?
If nothing else this little experiment makes me appriciate how much effort you have put into the P2!
Do you mind if I put this up on github? With an MIT license say?
Aside: I'm amazed this cheap Rigol scope, hacked from 50MHz to 100Mhz bandwidth, can display reasonably square bits flipping at 50MHz.
The compile time is one of the reasons I gave up on trying to modify the P1 Verilog code. I've gotten spoiled with fast software compile times. Working with Quartus seems like going back to the day when I submitted a card deck at a window and came back for the printout the next day.
Quartus certainly does put a damper on things. If it were not being able to simulate Chip's verilog with Icarus I would have given up at the first hurdle. Just type the verilog into vim, save and go! With a file watcher on the project directory the simulation is kicked off as soon as I hit :w
The Icarus simulator is slow though. So I'm looking at Verilator.
I guess the idea is to develop a design in small parts and test them with a simulator. Then you only have to do the time consuming FPGA building when you have an idea that things work well.
I'm curious to know how experienced chip designers, like Chip, deal with this.
Grr, I can't fault the Ryzen any longer. I've put all the BIOS settings back and even notched up a little extra on the overclocking.
For sure, the old install using kernel 4.8 still crashes out under load but I haven't been able to duplicate the earlier iso download errors I had on this kernel 4.10. I had two consecutive fails with differing md5 outcomes. Now, all is fine as long as I use the newer kernel.
Well, the overclocking is still within the XFR spec (https://en.wikipedia.org/wiki/Zen_(microarchitecture)#Desktop_processors) but I am seeing something in the area of 180 Watts pouring into the CPU when running Handbrake. System power exceeds 200 Watts with nothing of note doing anything else. That's one mean program.
Idle system power is 35 Watts, 30 Watts when not overclocked. This includes a GeForce GTX960 and four drives.
Made me a UART in Verilog. Well, "UAT", it's only the transmitter. Well, "AT", as it is not very universal.
Code looks like this:
//
// uartTx.v
//
// Simple UART transmiter.
// 115200 baud when driven from 50Mhz clock.
// Single byte buffer for concurrent loading while transmitting.
//
module uartTx (
input resn, // Reset, active low.
input clk, // Clock, (Use 50Mhz for 115200 baud).
input wr, // Writes data to holding register on rising clock
input [7:0] data, // Data to be transmitted.
output reg serialOut, // The serial outout.
output reg empty // TRUE when ready to accept next character.
);
// Internal Variables
reg [7:0] shifter;
reg [7:0] buffer;
reg [7:0] state;
reg [3:0] bitCount;
reg [19:0] bitTimer;
// UART TX Logic
always @ (posedge clk or negedge resn)
begin
if (!resn) begin
state <= 0;
buffer <= 0;
empty <= 1;
shifter <= 0;
serialOut <= 1;
bitCount <= 0;
bitTimer <= 0;
end else begin
if ((wr == 1) && (empty == 1)) begin
buffer <= data;
empty <= 0;
end
// Generate bit clock timer for 115200 baud from 50MHz clock
bitTimer <= bitTimer + 1;
if (bitTimer == 1302) begin
bitTimer <= 0;
end
if (bitTimer == 0) begin
case (state)
// Idle
0 : begin
if (!empty) begin
shifter <= buffer;
empty <= 1;
state <= 1;
bitCount <= 8;
serialOut <= 0;
end
end
// Transmitting
1 : begin
if (bitCount > 0) begin
bitCount <= bitCount - 1;
end
// Data bits
if (bitCount < 9 & bitCount > 0) begin
serialOut <= shifter[0];
shifter <= shifter >> 1;
end
// Stop bit
if (bitCount == 0) begin
serialOut <= 1;
state <= 0;
end
end
default : ;
endcase
end
end
end
endmodule
And a top level module to use it to output "Hello World!" from the DE0-Nano:
//
// blinky
//
// DE0-Nano pin outs.
// Signal Name FPGA Pin No. Description I/O Standard
// CLOCK_50 R8
// Signal Name FPGA Pin No. Description I/O Standard
// KEY[0] PIN_J15 Push-button[0] 3.3V
// KEY[1] PIN_E1 Push-button[1] 3.3V
// Signal Name FPGA Pin No. Description I/O Standard
// LED[0] PIN_A15 LED Green[0] 3.3V
// LED[1] PIN_A13 LED Green[1] 3.3V
// LED[2] PIN_B13 LED Green[2] 3.3V
// LED[3] PIN_A11 LED Green[3] 3.3V
// LED[4] PIN_D1 LED Green[4] 3.3V
// LED[5] PIN_F3 LED Green[5] 3.3V
// LED[6] PIN_B1 LED Green[6] 3.3V
// LED[7] PIN_L3 LED Green[7] 3.3V
// Signal Name FPGA Pin No. Description I/O Standard
// GPIO_10 PIN_F13 GPIO JP2, 2
// GPIO_11 PIN_T15 GPIO JP2, 4
// GPIO_13 PIN_T13 GPIO JP2, 6
// GPIO_15 PIN_T12 GPIO JP2, 8
// Make a slow clock from a fast one
module SlowIt (input FastClock, output reg SlowClock);
reg [25:0]R;
always @(posedge FastClock)
begin
R = R + 1;
SlowClock = R[22]; //(50*10^6)/(2^24) or 19.15 Hz
end
endmodule
module hello (
input resn, // Reset, active low.
input clk,
output serialOut // The serial outout.
);
// UART TX testing "Hello World1"
reg wr;
reg [7:0] data;
reg [3:0] state;
wire empty;
wire [7:0] greet [0:15];
assign greet[0] = "H";
assign greet[1] = "e";
assign greet[2] = "l";
assign greet[3] = "l";
assign greet[4] = "o";
assign greet[5] = " ";
assign greet[6] = "W";
assign greet[7] = "o";
assign greet[8] = "r";
assign greet[9] = "l";
assign greet[10] = "d";
assign greet[11] = "!";
assign greet[12] = 8'h00;
assign greet[13] = 8'h00;
assign greet[14] = 8'h00;
assign greet[15] = 8'h00;
reg [4:0] greetIdx;
uartTx t1 (
.resn(resn), // Reset, active low.
.clk(clk), // Clock, (Use 50Mhz for 115200 baud).
.wr(wr), // Writes data to holding register on rising clock
.data(data), // Data to be transmitted.
.serialOut(serialOut), // The serial outout.
.empty(empty) // TRUE when ready to accept next character.
);
always @(posedge clk or negedge resn)
begin
if (!resn) begin
state <= 0;
data <= 0;
wr <= 0;
greetIdx <= 0;
end else begin
case (state)
0 : begin
data <= greet[greetIdx];
greetIdx <= greetIdx + 1;
wr <= 1;
state <= state + 1;
end
1: begin
wr <= 0;
state <= state + 1;
end
2: begin
if (empty == 1) begin
state <= 0;
end
end
default : ;
endcase
end
end
endmodule
// The classic "Hello world" of hardware.
// Only this time using the xoroshiro128+ PRNG to drive 8 LEDs.
module blinky (input CLOCK_50, input reset_btn, output[7:0] LED, output[3:0] RND_OUT, output UART_TX);
// Slow down the clock
wire slowClock;
SlowIt slowit (.FastClock(CLOCK_50), .SlowClock(slowClock));
// Random flashing of green LEDs.
xoroshiro128plus r1 (.resn(reset_btn), .clk(slowClock), .out(LED));
// Full speed random wiggle of 4 GPIO pins
xoroshiro128plus r2 (.resn(reset_btn), .clk(CLOCK_50), .out(RND_OUT));
// Hello world !
hello h1 (.resn(reset_btn), .clk(CLOCK_50), .serialOut(UART_TX));
endmodule
And it works!
This is kind of hard work. Easy going with the Verilog simulator, type and run, type and run...(Like Javascript, Yay!) Then you hit Quartus to get it onto the FPGA. Many hours later....something starts to work.
Word of warning on another gotcha: Those Rigols are a bit touchy decoding a valid serial string correctly, but I suspect you've already discovered that.
Heater,
I've only ever compiled the finished designs from here. When starting a fresh design like this, how much editing of support files is there backing your posted verilog? Chip's designs seem to have a bunch of framing VHDL.
I have never used any such decoding feature of any scope. As such I'm just poking around in it's menus and hoping to see something. Don't know if RTFM helps.
Which leaves me not knowing if any errors I see are due to the scope feature, my configuration of it or my crappy Verilog!
It does show errors over 38400 baud. Of course we want faster than that. I'll hook up a Prop Plug or some such at some point.
As for fresh designs this is what I have been doing here:
Step 1:
Using a favorite editor, vim has good Verilog syntax highlighting, write the code for a new module.
At the same time write a "test bench" that will instantiate the module, poke inputs at it and display/log the outputs.
This is quite fun. Hack code, run simulation, fix code, run simulation. A very nice fast turn around time.
Step 2:
Drop the new module into a Quartus project.
This will probably need a new top level module to instantiate your new module and hook it up to actual clocks and pins on the FPGA. See blinky module above. (I really should have put the hello module in a separate file.
To make the connection from signals in your code to actual pins you use the "pin planner" (Assignemts -> Pin Planner in the menu). I think you need to have Quartus build the code cleanly first, then the unconnected signals in your code show up in the Pin Planner. Use the Pin Planner to assign signal to pin, the rebuild again.
Then it's time to program the FPGA and see if it flies.
So, in answer to your question, I have only actually edited the text of the Verilog I use: blinky.v, xoroshiro128.v, uartTx.v
Of course Quartus makes a ton of files in the project directory. I think blinky.qpf is a project file, there is nothing much in it. There is a blinky.qsf that contains all the pin mapping and a couplle of other things.
I'm hoping that this is all I need to be able to reproduce the thing from a backup and for a github repo.
Here is the test bench I used while developing uartTx:
module uart_tb;
// Define input signals (reg)
reg resn;
reg clk;
reg wr;
reg [7:0] data;
// Define output signals (wire)
wire serialOut;
wire empty;
// Instantiate DUT.
tx t1 (
.resn(resn),
.clk(clk),
.wr(wr),
.data(data),
.serialOut(serialOut),
.empty(empty)
);
// Initialize all inputs
initial
begin
resn = 0;
clk = 0;
wr = 0;
data = 0;
end
// Generate a clock tick
always
#5clk = !clk;
// Specify file for waveform dump
initial begin
$dumpfile ("counter.vcd");
$dumpvars;
end
// Monitor all signals
initial begin
$display("\tclk,\tresn,\twr,\tdata,\tserialOut,\tempty");
$monitor("\t%b,\t%b,\t%b,\t%h,\t%b,\t\t%b", clk, resn, wr, data, serialOut, empty);
end
event reset_trigger;
event reset_done_trigger;
initial begin
forever begin
@ (reset_trigger);
@ (negedge clk);
resn = 0;
@ (negedge clk);
resn = 1;
-> reset_done_trigger;
end
end
initial
begin: TEST_CASE
#10 -> reset_trigger;
@ (reset_done_trigger);
$write("reset done\n");
@ (negedge clk);
$write("loading first char.\n");
data = 8'h00;
wr = 1;
@ (negedge clk) wr = 0;
repeat (10) begin
@ (posedge empty);
$write("empty: reloading\n");
@ (negedge clk)
data = data + 1;
wr = 1;
@ (negedge clk) wr = 0;
end
@ (posedge empty) $finish;
end
endmodule
I thought I'd just borrow a UART example off the net. Didn't like any of them so I started from scratch. A good exercise I guess.
What chip does it use ?
Start testing with 115200, and then increase.
Most recent FTDI parts can get up towards 3MBd, with a 12M/N virtual baud clock.
If you happen to have a FT232H or FT2232H (sometimes found on Eval boards) you can run those to 12MBd
You could add a handshake line, to make things highest-speed (aka slow PC ) tolerant ?
Somehow, you're writing C programs in Verilog. Your design approach is quite behavioral. All of my code is like hardware described in text, since I come from a schematic mindset. I know what kind of logic it will compile to. You are working at a higher level of abstraction.
Thanks for the ""wow". I guess that means my uart is not total gibberish
Somehow, you're writing C programs in Verilog.
I like to think of it as writing Javascript programs in Verilog. That might sound crazy but there is some conceptual similarity to the way everything Javascript is event driven. You can't just write reams of sequential code with loops, function calls, recursion, etc. You have to make every everything hang off an event and make it short, fast and sweet.
For example:
// JS. Increment X every button press
button.on('interrupt', function () {
x = x + 1;
});
// Verilog. Increment X every button press
always @ (posedge button)
begin
x = x + 1;
end
Hacking around with Verilog with a simulator like Icarus has the same edit, run, edit, run feel of writing JS for node.js.
Your design approach is quite behavioral.
Ha, that's high highfalutin talk. I don't have an approach yet. I just hoovered up a bunch of verilog tutorials on the net (all of which seem to be awful), looked at some example codes, then threw bits of what I learn into the UART and ask Icarus if it understands it!
To be honest I don't have a feel for the differences between structural, behavorial, RTL, etc design yet. It all seems a bit vague to me. Clearly Verilog has a lot of stuff that cannot be synthesized and looks like a egual programming language, see test bench above.
I don't have a feel for how much and what kind of logic the code generates. Or what time it may take to produce an output. Although it's interesting to look at the schematics Quartus produces.
How are you getting any timing analysis out of Quartus?
How are you getting any timing analysis out of Quartus?
Just click on the clock-looking icon up at the top of the Quartus window. Then, double-click "Report Timing" and hit enter to get it started. It will show you the slowest paths. It's pretty self-explanatory.
That's neat you're able to get into Verilog so quickly.
Comments
I have 8 blinky green LEDs twinkling at random.
What a struggle. 10 hours from idea to blinky. What with the Altera/Intel web site suffering maintenance this morning, the long winded registration, monster down load and install. Then WTF is all this? Quartus is huge and complicated (and slow). Seems to have a billion options that one does not know if one needs or not. Then getting the top level module sorted out and the pin assignments. Then WTF is the USB blaster? Another monster download....
Grrr...
Anyway something works. Except I also directed an instance of the PRNG to some GPIO pins but I can't see any action there on the scope at all. Pin assignments have been checked and checked...
Here is the top level module. I renamed Chip's rnd to xoroshiro128plus.
Now I need to put the bit shuffling in and figure out how to make a UART to pump the random bits out of there as fast as possible.
If you have a FT232H/FT2232H they can pump up to 12MBd streams.
FS USB Uarts are more modest, better ones can manage 3~4Mbd one way, best in class can do ~ 9Mbd effective rates,
Just a DE0 Nano and a USB cable for the USB Blaster.
I do have a Parallax "DE0-NANO PROP2 EMULATOR" expansion board and a Prop Plug to connect to it. Not in use at the moment.
I have no idea what speed the Prop Plug can achieve.
Even so, at the max speed of a USB interface I think we end up getting those random bits much slower than a C code version running on the PC.
I should look into the Verilator Verilog to C++ compiler, it did not work out of the box for me.
On the other hand...I'm getting into this idea of generating logic for an actual FPGA.
Anyone, have any idea why I cannot get output on the DE0-Nano GPIO pins ?
Actually, I was totally stunned when the 8 green LEDs started blinking at random the first time I loaded it!
I have no idea where my GPIO output has gone.
There is a ton of warnings in the build output that give no clue as to what may be wrong.
For example: Hmm...Sounds like a likely problem. What "I/O Assignment Warnings report"?. Where?
10 years ago or so I started messing with VHDL. I cooked up a brilliant VHDL version of a 3-way loudspeaker crossover circuit. From an analog opamp design. It simulated fantastically under GHDL. Frequency response exactly as planned. It was doomed because most of it was not synthesizable into an FPGA. I wish these simulators would tell you what is real and what is not. A friend of mine adapted the code into a plugin for some Windows audio processing software in Java or whatever and said it sounded great!
Then there was the Propeller...
And now, here we are. Back to square one...
My Verilog looks like the post above: http://forums.parallax.com/discussion/comment/1404400/#Comment_1404400
Where the xoroshiro128 module is Chip's code posted earlier here but renamed.
My not working Verilog produces messages like the following when I build it: OK, sounds like connections are wrong.
But what "Connectivity Checks report folder" and what " I/O Assignment Warnings report"?
Where? How?
Maybe I'm just getting too tired after 17 hours fighting with this. A Google search or a dozen turns up nothing.
It says I have a bunch of unused signals. Quite so.
Also the "Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" Seems to be irrelevant.
Still I have no output on GPIO....
I don't know that any pins work except the ones driving the LEDs.
So I swapped the high speed and low speed PRNG outputs around.
The result was the LEDs were lit up all the time. As expected as the random bits are hitting them at 50MHz.
The GPIO did not move!
I think what I need is the DE0-Nano pin assignment file. Which I cannot find anywhere. I guess it's on the CD that came with the board. If I ever had that.
Or I assign all the GPIO pins manually and see if I can drive any of them!
After 20 hours at this I think I'm about to pass out...
On totally the other GPIO header connector and pins in some random position.
3 channels of lovely random bits switching at 50MHz. As seen by my equally lovely Rigol DS1054: (Hacked to 100MHz bandwidth, shhh, don't tell any one)
There is actually the 4th channel but it's a bit hard hang the scope probe on.
In the DE0-Nano data sheet there is GPIO_11, for example, and also GPIO_011.
Who would notice that when they are half asleep? And who would think a leading zero matters?!
Grrr...
Anyway, mystery solved.
Now to get on with my CPU design...
Congratulations, Heater! You've got the Verilog/FPGA flow going now. Upward and onward.
More combinations to try yet ...
I don't know about "flow". Working with Quartus feels like trying to wade through some non newtonian fluid just now. This is only a tiny bit of Verilog and it takes an age to synthesize. How long does it take to build a working P2? How often do you do that? I guess the question is what is your work flow when tweaking the P2 code?
If nothing else this little experiment makes me appriciate how much effort you have put into the P2!
Do you mind if I put this up on github? With an MIT license say?
Aside: I'm amazed this cheap Rigol scope, hacked from 50MHz to 100Mhz bandwidth, can display reasonably square bits flipping at 50MHz.
The Icarus simulator is slow though. So I'm looking at Verilator.
I guess the idea is to develop a design in small parts and test them with a simulator. Then you only have to do the time consuming FPGA building when you have an idea that things work well.
I'm curious to know how experienced chip designers, like Chip, deal with this.
For sure, the old install using kernel 4.8 still crashes out under load but I haven't been able to duplicate the earlier iso download errors I had on this kernel 4.10. I had two consecutive fails with differing md5 outcomes. Now, all is fine as long as I use the newer kernel.
Idle system power is 35 Watts, 30 Watts when not overclocked. This includes a GeForce GTX960 and four drives.
Code looks like this:
And a top level module to use it to output "Hello World!" from the DE0-Nano: And it works!
This is kind of hard work. Easy going with the Verilog simulator, type and run, type and run...(Like Javascript, Yay!) Then you hit Quartus to get it onto the FPGA. Many hours later....something starts to work.
Now to hook the PRNG to the serial port.
Anyone know how fast a Prop Plug will work?
Word of warning on another gotcha: Those Rigols are a bit touchy decoding a valid serial string correctly, but I suspect you've already discovered that.
Heater,
I've only ever compiled the finished designs from here. When starting a fresh design like this, how much editing of support files is there backing your posted verilog? Chip's designs seem to have a bunch of framing VHDL.
Which leaves me not knowing if any errors I see are due to the scope feature, my configuration of it or my crappy Verilog!
It does show errors over 38400 baud. Of course we want faster than that. I'll hook up a Prop Plug or some such at some point.
As for fresh designs this is what I have been doing here:
Step 1:
Using a favorite editor, vim has good Verilog syntax highlighting, write the code for a new module.
At the same time write a "test bench" that will instantiate the module, poke inputs at it and display/log the outputs.
This is quite fun. Hack code, run simulation, fix code, run simulation. A very nice fast turn around time.
Step 2:
Drop the new module into a Quartus project.
This will probably need a new top level module to instantiate your new module and hook it up to actual clocks and pins on the FPGA. See blinky module above. (I really should have put the hello module in a separate file.
To make the connection from signals in your code to actual pins you use the "pin planner" (Assignemts -> Pin Planner in the menu). I think you need to have Quartus build the code cleanly first, then the unconnected signals in your code show up in the Pin Planner. Use the Pin Planner to assign signal to pin, the rebuild again.
Then it's time to program the FPGA and see if it flies.
So, in answer to your question, I have only actually edited the text of the Verilog I use: blinky.v, xoroshiro128.v, uartTx.v
Of course Quartus makes a ton of files in the project directory. I think blinky.qpf is a project file, there is nothing much in it. There is a blinky.qsf that contains all the pin mapping and a couplle of other things.
I'm hoping that this is all I need to be able to reproduce the thing from a backup and for a github repo.
Here is the test bench I used while developing uartTx: I thought I'd just borrow a UART example off the net. Didn't like any of them so I started from scratch. A good exercise I guess.
Start testing with 115200, and then increase.
Most recent FTDI parts can get up towards 3MBd, with a 12M/N virtual baud clock.
If you happen to have a FT232H or FT2232H (sometimes found on Eval boards) you can run those to 12MBd
You could add a handshake line, to make things highest-speed (aka slow PC ) tolerant ?
Somehow, you're writing C programs in Verilog. Your design approach is quite behavioral. All of my code is like hardware described in text, since I come from a schematic mindset. I know what kind of logic it will compile to. You are working at a higher level of abstraction.
I wonder how Heater's code compiles down, as in does it create tiny state machines?
Thanks for the ""wow". I guess that means my uart is not total gibberish I like to think of it as writing Javascript programs in Verilog. That might sound crazy but there is some conceptual similarity to the way everything Javascript is event driven. You can't just write reams of sequential code with loops, function calls, recursion, etc. You have to make every everything hang off an event and make it short, fast and sweet.
For example:
Hacking around with Verilog with a simulator like Icarus has the same edit, run, edit, run feel of writing JS for node.js. Ha, that's high highfalutin talk. I don't have an approach yet. I just hoovered up a bunch of verilog tutorials on the net (all of which seem to be awful), looked at some example codes, then threw bits of what I learn into the UART and ask Icarus if it understands it!
To be honest I don't have a feel for the differences between structural, behavorial, RTL, etc design yet. It all seems a bit vague to me. Clearly Verilog has a lot of stuff that cannot be synthesized and looks like a egual programming language, see test bench above.
I don't have a feel for how much and what kind of logic the code generates. Or what time it may take to produce an output. Although it's interesting to look at the schematics Quartus produces.
How are you getting any timing analysis out of Quartus?
Just click on the clock-looking icon up at the top of the Quartus window. Then, double-click "Report Timing" and hit enter to get it started. It will show you the slowest paths. It's pretty self-explanatory.
That's neat you're able to get into Verilog so quickly.