Add ram test and verilator in fpga DEMO.

This commit is contained in:
colin 2022-02-09 12:47:35 +00:00
parent 3c3cfccfd5
commit 18c8352c09
18 changed files with 11794 additions and 61 deletions

6
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"files.associations": {
"BUILD": "bazel",
"memory": "cpp"
}
}

View File

@ -6,6 +6,27 @@
sudo apt-get install build-essential clang bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev build-essential libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-test-dev libboost-iostreams-dev python3.9-dev libboost-iostreams-dev libeigen3-dev libudev-dev cmake python3-pip gcc gdb autoconf automake libtool libusb-dev libusb-1.0-0-dev python2.7-dev
```
## install verilator form source to use new version
```
git clone https://github.com/verilator/verilator # Only first time
# Every time you need to build:
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
unset VERILATOR_ROOT # For bash
cd verilator
git pull # Make sure git repository is up-to-date
git tag # See what versions exist
#git checkout master # Use development branch (e.g. recent bug fixes)
#git checkout stable # Use most recent stable release
#git checkout v{version} # Switch to specified release version
autoconf # Create ./configure script
./configure # Configure and create Makefile
make -j `nproc` # Build Verilator itself (if error, try just 'make')
sudo make install
```
## install yosys
```

2
fpga/ram/.gitignore vendored
View File

@ -3,3 +3,5 @@
*.config
*.ys
*.json
obj_dir
logs

View File

@ -1,11 +1,12 @@
TARGET=ram
TARGET=top
OBJS+=ram.v
OBJS+=top.sv
OBJS+=bram.sv
all: ${TARGET}.bit
$(TARGET).json: $(OBJS)
yosys -p "read_verilog $(OBJS); synth_ecp5 -top ${TARGET} -json $@"
yosys -p "read_verilog -sv $(OBJS); synth_ecp5 -top ${TARGET} -json $@"
$(TARGET).config: $(TARGET).json
nextpnr-ecp5 --25k --package CABGA381 --speed 6 --json $< --textcfg $@ --lpf $(TARGET).lpf --freq 65
@ -20,6 +21,11 @@ prog: ${TARGET}.svf
./dapprog ${TARGET}.svf
clean:
rm -f *.svf *.bit *.config *.ys *.json
rm -rf *.svf *.bit *.config *.ys *.json obj_dir logs
verilator:
rm -rf obj_dir logs
verilator -Wall --cc --exe --build --trace sim_main.cpp $(OBJS)
obj_dir/Vtop +trace
.PHONY: prog clean

31
fpga/ram/bram.sv Normal file
View File

@ -0,0 +1,31 @@
module bram(
input clk,
input re,
input we,
input [DEPTH-1:0] addr_rd,
input [DEPTH-1:0] addr_wr,
output logic [WIDTH-1:0] data_rd,
input [WIDTH-1:0] data_wr
);
parameter WIDTH=8;
parameter DEPTH=8;
parameter SIZE=(1<<DEPTH);
logic [WIDTH-1:0] ram [0:SIZE-1];
initial begin
$readmemh("data.bin", ram);
end
always @(posedge clk) begin
if (we) begin
ram[addr_wr] <= data_wr;
end
end
always @(posedge clk) begin
if (re) begin
data_rd <= ram[addr_rd];
end
end
endmodule

8192
fpga/ram/data.bin Normal file

File diff suppressed because it is too large Load Diff

1088
fpga/ram/egrep Normal file

File diff suppressed because it is too large Load Diff

1088
fpga/ram/grep Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +0,0 @@
LOCATE COMP "clk_i" SITE "P3";
IOBUF PORT "clk_i" IO_TYPE=LVCMOS33;
FREQUENCY PORT "clk_i" 25 MHZ;
LOCATE COMP "led_o" SITE "U16";
IOBUF PORT "led_o" IO_TYPE=LVCMOS33;

View File

@ -1,49 +0,0 @@
module ram_single(dataout, addr, datain, we, clk);
output[7:0] dataout;
input [7:0] datain;
input [10:0] addr;
input we, clk;
reg [7:0] mem [2048:0];
always @(posedge clk) begin
if (we)
mem[addr] <= datain;
dataout <= mem[addr];
end
endmodule
module ram (
input clk_i,
output reg led_o
);
localparam MAX = 2_500_000_0;
localparam WIDTH = $clog2(MAX);
wire[7:0] dataout;
reg[7:0] datain;
reg[10:0] addr;
reg we;
ram_single mem(.dataout(dataout), .addr(addr), .datain(datain), .we(we), .clk(clk_i));
wire clk_s;
assign clk_s = clk_i;
reg [WIDTH-1:0] cpt_s;
wire [WIDTH-1:0] cpt_next_s = cpt_s + 1'b1;
wire end_s = cpt_s == MAX-1;
wire nextAddr = addr + 1'b1;
wire dataAdd = dataout + 1'b1;
always @(posedge clk_s) begin
cpt_s <= cpt_next_s;
addr <= nextAddr;
datain <= dataAdd;
led_o <= dataout[0];
// if (end_s)
// led_o <= ~led_o;
end
endmodule

43
fpga/ram/sim_main.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <verilated.h>
#include <memory>
#include "Vtop.h"
#include "verilated_vcd_c.h"
double sc_time_stamp() { return 0; }
int main(int argc, char** argv, char** env) {
Verilated::mkdir("logs");
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
contextp->debug(0);
contextp->randReset(2);
contextp->traceEverOn(true);
contextp->commandArgs(argc, argv);
const std::unique_ptr<Vtop> top{new Vtop{contextp.get(), "TOP"}};
top->clk = 0;
Verilated::traceEverOn(true);
VerilatedVcdC* tfp = new VerilatedVcdC;
top->trace(tfp, 99); // Trace 99 levels of hierarchy
tfp->open("logs/vlt_dump.vcd");
uint64_t steps = 10000;
while (!contextp->gotFinish() && steps) {
contextp->timeInc(1); // 1 timeprecision period passes...
top->clk = !top->clk;
top->eval();
steps--;
tfp->dump(contextp->time());
}
tfp->close();
top->final();
return 0;
}

11
fpga/ram/top.lpf Normal file
View File

@ -0,0 +1,11 @@
LOCATE COMP "clk" SITE "P3";
IOBUF PORT "clk" IO_TYPE=LVCMOS33;
FREQUENCY PORT "clk" 25 MHZ;
LOCATE COMP "key" SITE "P4";
IOBUF PORT "key" IO_TYPE=LVCMOS33;
LOCATE COMP "led_o" SITE "U16";
IOBUF PORT "led_o" IO_TYPE=LVCMOS33;

49
fpga/ram/top.sv Normal file
View File

@ -0,0 +1,49 @@
module top(
input clk,
output reg led_o
);
parameter WIDTH=8;
parameter DEPTH=16;
parameter SIZE=(1<<DEPTH);
reg [DEPTH-1:0] read_addr;
reg [DEPTH-1:0] write_addr;
wire [DEPTH-1:0] read_addr_next = read_addr + 1'b1;
wire [DEPTH-1:0] write_addr_next = write_addr + 1'b1;
wire [WIDTH-1:0] read_data;
reg [WIDTH-1:0] write_data;
bram #(
.WIDTH(WIDTH),
.DEPTH(DEPTH),
.SIZE(SIZE)
) bram_i (
.clk(clk),
.re(1'b1),
.we(1'b1),
.addr_rd(read_addr),
.addr_wr(write_addr),
.data_rd(read_data),
.data_wr(write_data)
);
always @(posedge clk) begin
led_o <= read_data[0];
write_data <= {read_data[6:0],read_data[7]};
read_addr <= read_addr_next;
write_addr <= write_addr_next;
end
initial begin
$display(" Model running...\n");
read_addr = 1;
write_addr = 0;
write_data = 0;
end
endmodule

1089
fpga/ram/xargs Normal file

File diff suppressed because it is too large Load Diff

7
fpga/verilator/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.svf
*.bit
*.config
*.ys
*.json
obj_dir
logs

13
fpga/verilator/Makefile Normal file
View File

@ -0,0 +1,13 @@
TARGET=top
OBJS+=top.v
clean:
rm -rf *.svf *.bit *.config *.ys *.json obj_dir logs
verilator:
rm -rf obj_dir
verilator -Wall --cc --exe --build --trace sim_main.cpp $(OBJS)
obj_dir/Vtop +trace
.PHONY: prog clean

113
fpga/verilator/sim_main.cpp Normal file
View File

@ -0,0 +1,113 @@
#include <verilated.h>
#include <memory>
#include "Vtop.h"
double sc_time_stamp() { return 0; }
int main(int argc, char** argv, char** env) {
// Prevent unused variable warnings
if (false && argc && argv && env) {
}
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// Construct a VerilatedContext to hold simulation time, etc.
// Multiple modules (made later below with Vtop) may share the same
// context to share time, or modules may have different contexts if
// they should be independent from each other.
// Using unique_ptr is similar to
// "VerilatedContext* contextp = new VerilatedContext" then deleting at end.
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
// Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs argument parsing
contextp->debug(0);
// Randomization reset policy
// May be overridden by commandArgs argument parsing
contextp->randReset(2);
// Verilator must compute traced signals
contextp->traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model
contextp->commandArgs(argc, argv);
// Construct the Verilated model, from Vtop.h generated from Verilating
// "top.v". Using unique_ptr is similar to "Vtop* top = new Vtop" then
// deleting at end. "TOP" will be the hierarchical name of the module.
const std::unique_ptr<Vtop> top{new Vtop{contextp.get(), "TOP"}};
// Set Vtop's input signals
top->reset_l = !0;
top->clk = 0;
top->in_small = 1;
top->in_quad = 0x1234;
top->in_wide[0] = 0x11111111;
top->in_wide[1] = 0x22222222;
top->in_wide[2] = 0x3;
uint64_t steps = 1000;
// Simulate until $finish
while (!contextp->gotFinish() && steps) {
// Historical note, before Verilator 4.200 Verilated::gotFinish()
// was used above in place of contextp->gotFinish().
// Most of the contextp-> calls can use Verilated:: calls instead;
// the Verilated:: versions simply assume there's a single context
// being used (per thread). It's faster and clearer to use the
// newer contextp-> versions.
contextp->timeInc(1); // 1 timeprecision period passes...
// Historical note, before Verilator 4.200 a sc_time_stamp()
// function was required instead of using timeInc. Once timeInc()
// is called (with non-zero), the Verilated libraries assume the
// new API, and sc_time_stamp() will no longer work.
// Toggle a fast (time/2 period) clock
top->clk = !top->clk;
// Toggle control signals on an edge that doesn't correspond
// to where the controls are sampled; in this example we do
// this only on a negedge of clk, because we know
// reset is not sampled there.
if (!top->clk) {
if (contextp->time() > 1 && contextp->time() < 10) {
top->reset_l = !1; // Assert reset
} else {
top->reset_l = !0; // Deassert reset
}
// Assign some other inputs
top->in_quad += 0x12;
}
// Evaluate model
// (If you have multiple models being simulated in the same
// timestep then instead of eval(), call eval_step() on each, then
// eval_end_step() on each. See the manual.)
top->eval();
// Read outputs
// VL_PRINTF("[%" PRId64 "] clk=%x rstl=%x iquad=%" PRIx64 " -> oquad=%" PRIx64
// " owide=%x_%08x_%08x\n",
// contextp->time(), top->clk, top->reset_l, top->in_quad,
// top->out_quad, top->out_wide[2], top->out_wide[1],
// top->out_wide[0]);
steps--;
}
// Final model cleanup
top->final();
// Coverage analysis (calling write only after the test is known to pass)
#if VM_COVERAGE
Verilated::mkdir("logs");
contextp->coveragep()->write("logs/coverage.dat");
#endif
return 0;
}

31
fpga/verilator/top.v Normal file
View File

@ -0,0 +1,31 @@
module top
(
input clk,
input reset_l,
output wire [1:0] out_small,
output wire [39:0] out_quad,
output wire [69:0] out_wide,
input [1:0] in_small,
input [39:0] in_quad,
input [69:0] in_wide
);
assign out_small = ~reset_l ? '0 : (in_small + 2'b1);
assign out_quad = ~reset_l ? '0 : (in_quad + 40'b1);
assign out_wide = ~reset_l ? '0 : (in_wide + 70'b1);
always @(posedge clk) begin
end
initial begin
if ($test$plusargs("trace") != 0) begin
$display("[%0t] Tracing to logs/vlt_dump.vcd...\n", $time);
$dumpfile("logs/vlt_dump.vcd");
$dumpvars();
end
$display("[%0t] Model running...\n", $time);
end
endmodule