Add ram test and verilator in fpga DEMO.
This commit is contained in:
parent
3c3cfccfd5
commit
18c8352c09
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"BUILD": "bazel",
|
||||
"memory": "cpp"
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
```
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
*.config
|
||||
*.ys
|
||||
*.json
|
||||
obj_dir
|
||||
logs
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
*.svf
|
||||
*.bit
|
||||
*.config
|
||||
*.ys
|
||||
*.json
|
||||
obj_dir
|
||||
logs
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
Loading…
Reference in New Issue