6953 lines
204 KiB
Plaintext
6953 lines
204 KiB
Plaintext
module M_%MODULE%_mem_%NAME%(
|
|
input [%WENABLE0_WIDTH%:0] in_%NAME%_wenable0,
|
|
input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata0,
|
|
input [%ADDR0_WIDTH%:0] in_%NAME%_addr0,
|
|
input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1,
|
|
input [%DATA_WIDTH%:0] in_%NAME%_wdata1,
|
|
input [%ADDR1_WIDTH%:0] in_%NAME%_addr1,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1,
|
|
input %CLOCK%0,
|
|
input %CLOCK%1
|
|
);
|
|
reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0];
|
|
always @(posedge %CLOCK%0) begin
|
|
out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0];
|
|
if (in_%NAME%_wenable0) begin
|
|
out_%NAME%_rdata0 <= in_%NAME%_wdata0;
|
|
buffer[in_%NAME%_addr0] <= in_%NAME%_wdata0;
|
|
end
|
|
end
|
|
always @(posedge %CLOCK%1) begin
|
|
out_%NAME%_rdata1 <= buffer[in_%NAME%_addr1];
|
|
if (in_%NAME%_wenable1) begin
|
|
out_%NAME%_rdata1 <= in_%NAME%_wdata1;
|
|
buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1;
|
|
end
|
|
end
|
|
%INITIAL%
|
|
endmodule
|
|
module M_%MODULE%_mem_%NAME%(
|
|
input [%WENABLE_WIDTH%:0] in_%NAME%_wenable,
|
|
input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata,
|
|
input [%ADDR_WIDTH%:0] in_%NAME%_addr,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata,
|
|
input %CLOCK%
|
|
);
|
|
reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0];
|
|
always @(posedge %CLOCK%) begin
|
|
if (in_%NAME%_wenable) begin
|
|
buffer[in_%NAME%_addr] <= in_%NAME%_wdata;
|
|
end
|
|
out_%NAME%_rdata <= buffer[in_%NAME%_addr];
|
|
end
|
|
%INITIAL%
|
|
endmodule
|
|
module M_%MODULE%_mem_%NAME%(
|
|
input [%WENABLE0_WIDTH%:0] in_%NAME%_wenable0,
|
|
input %DATA_TYPE% [%DATA_WIDTH%:0] in_%NAME%_wdata0,
|
|
input [%ADDR0_WIDTH%:0] in_%NAME%_addr0,
|
|
input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1,
|
|
input [%DATA_WIDTH%:0] in_%NAME%_wdata1,
|
|
input [%ADDR1_WIDTH%:0] in_%NAME%_addr1,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1,
|
|
input %CLOCK%0,
|
|
input %CLOCK%1
|
|
);
|
|
reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0];
|
|
always @(posedge %CLOCK%0) begin
|
|
if (in_%NAME%_wenable0) begin
|
|
buffer[in_%NAME%_addr0] <= in_%NAME%_wdata0;
|
|
end else begin
|
|
out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0];
|
|
end
|
|
end
|
|
always @(posedge %CLOCK%1) begin
|
|
if (in_%NAME%_wenable1) begin
|
|
buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1;
|
|
end else begin
|
|
out_%NAME%_rdata1 <= buffer[in_%NAME%_addr1];
|
|
end
|
|
end
|
|
%INITIAL%
|
|
endmodule
|
|
module M_%MODULE%_mem_%NAME%(
|
|
input [%ADDR0_WIDTH%:0] in_%NAME%_addr0,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata0,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata1,
|
|
input [%WENABLE1_WIDTH%:0] in_%NAME%_wenable1,
|
|
input [%DATA_WIDTH%:0] in_%NAME%_wdata1,
|
|
input [%ADDR1_WIDTH%:0] in_%NAME%_addr1,
|
|
input %CLOCK%0,
|
|
input %CLOCK%1
|
|
);
|
|
reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0];
|
|
always @(posedge %CLOCK%0) begin
|
|
out_%NAME%_rdata0 <= buffer[in_%NAME%_addr0];
|
|
end
|
|
always @(posedge %CLOCK%1) begin
|
|
if (in_%NAME%_wenable1) begin
|
|
buffer[in_%NAME%_addr1] <= in_%NAME%_wdata1;
|
|
end
|
|
end
|
|
%INITIAL%
|
|
endmodule
|
|
module M_%MODULE%_mem_%NAME%(
|
|
input [%ADDR_WIDTH%:0] in_%NAME%_addr,
|
|
output reg %DATA_TYPE% [%DATA_WIDTH%:0] out_%NAME%_rdata,
|
|
input %CLOCK%
|
|
);
|
|
reg %DATA_TYPE% [%DATA_WIDTH%:0] buffer[%DATA_SIZE%:0];
|
|
always @(posedge %CLOCK%) begin
|
|
out_%NAME%_rdata <= buffer[in_%NAME%_addr];
|
|
end
|
|
%INITIAL%
|
|
endmodule
|
|
// ----------------------- memory_ports.ice -----------
|
|
// @sylefeb - Silice standard library
|
|
// Memory port interfaces
|
|
// 2020-09-03
|
|
|
|
// single port BRAM
|
|
|
|
interface bram_port {
|
|
output! addr,
|
|
output! wenable,
|
|
input rdata,
|
|
output! wdata,
|
|
}
|
|
|
|
// single port BROM
|
|
|
|
interface brom_port {
|
|
output! addr,
|
|
input rdata,
|
|
}
|
|
|
|
// dual port BRAM
|
|
|
|
interface dualbram_port0 {
|
|
output! addr0,
|
|
output! wenable0,
|
|
input rdata0,
|
|
output! wdata0,
|
|
}
|
|
|
|
interface dualbram_port1 {
|
|
output! addr1,
|
|
output! wenable1,
|
|
input rdata1,
|
|
output! wdata1,
|
|
}
|
|
|
|
// simple dual port BRAM
|
|
|
|
interface simple_dualbram_port0 {
|
|
output! addr0,
|
|
input rdata0,
|
|
}
|
|
|
|
interface simple_dualbram_port1 {
|
|
output! addr1,
|
|
output! wenable1,
|
|
output! wdata1,
|
|
}
|
|
|
|
interface bram_ports {
|
|
output! addr0,
|
|
output! wenable0,
|
|
input rdata0,
|
|
output! wdata0,
|
|
output! addr1,
|
|
output! wenable1,
|
|
input rdata1,
|
|
output! wdata1,
|
|
}
|
|
|
|
// ----------------------- end of memory_ports.ice ----
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
// Sylvain Lefebvre 2019-09-26
|
|
|
|
#include "VgaChip.h"
|
|
#include "video_out.h"
|
|
|
|
VgaChip::VgaChip(int color_depth)
|
|
{
|
|
m_VideoOut = new VideoOut(
|
|
0/*debug*/,color_depth/*color depth*/,0/*polarity*/,
|
|
640 ,16,96,48,
|
|
480 ,10,2,33,
|
|
"vgaout");
|
|
}
|
|
|
|
VgaChip::~VgaChip()
|
|
{
|
|
delete (m_VideoOut);
|
|
}
|
|
|
|
void VgaChip::eval(
|
|
vluint8_t clk,
|
|
vluint8_t vs,
|
|
vluint8_t hs,
|
|
vluint8_t red,
|
|
vluint8_t green,
|
|
vluint8_t blue)
|
|
{
|
|
m_VideoOut->eval_RGB_HV(clk,vs,hs,red,green,blue);
|
|
}
|
|
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
//
|
|
// Based on code from the MCC216 project (https://github.com/fredrequin/fpga_1943)
|
|
// (c) Frederic Requin, GPL v3 license
|
|
//
|
|
|
|
#include "verilated.h"
|
|
#include "video_out.h"
|
|
#include "LibSL/Image/Image.h"
|
|
#include "LibSL/Image/ImageFormat_TGA.h"
|
|
#include "LibSL/Math/Vertex.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
using namespace LibSL::Image;
|
|
using namespace LibSL::Math;
|
|
|
|
ImageFormat_TGA g_RegisterFormat_TGA;
|
|
|
|
// Constructor
|
|
VideoOut::VideoOut(vluint8_t debug, vluint8_t depth, vluint8_t polarity,
|
|
vluint16_t hactive, vluint16_t hfporch_, vluint16_t hspulse_, vluint16_t hbporch_,
|
|
vluint16_t vactive, vluint16_t vfporch_, vluint16_t vspulse_, vluint16_t vbporch_,
|
|
const char *file)
|
|
{
|
|
// color depth
|
|
if (depth <= 8) {
|
|
bit_mask = (1 << depth) - 1;
|
|
bit_shift = (int)(8 - depth);
|
|
} else {
|
|
bit_mask = (vluint8_t)0xFF;
|
|
bit_shift = (int)0;
|
|
}
|
|
// synchros polarities
|
|
hs_pol = (polarity & HS_POS_POL) ? (vluint8_t)1 : (vluint8_t)0;
|
|
vs_pol = (polarity & VS_POS_POL) ? (vluint8_t)1 : (vluint8_t)0;
|
|
// screen format initialized
|
|
hor_size = hactive;
|
|
ver_size = vactive;
|
|
// record synch values
|
|
hfporch = hfporch_;
|
|
hspulse = hspulse_;
|
|
hbporch = hbporch_;
|
|
vfporch = vfporch_;
|
|
vspulse = vspulse_;
|
|
vbporch = vbporch_;
|
|
// debug mode
|
|
dbg_on = debug;
|
|
// allocate the pixels
|
|
std::cerr << hactive << " x " << vactive << " x " << (int)depth << std::endl;
|
|
pixels.allocate((int)hactive, (int)vactive);
|
|
// copy the filename
|
|
filename = std::string(file);
|
|
// internal variables cleared
|
|
hcount = (vluint16_t)hor_size;
|
|
vcount = (vluint16_t)ver_size;
|
|
prev_clk = (vluint8_t)0;
|
|
prev_hs = (vluint8_t)0;
|
|
prev_vs = (vluint8_t)0;
|
|
dump_ctr = (int)0;
|
|
// synch
|
|
v_sync_stage = e_Front;
|
|
h_sync_stage = e_Front;
|
|
v_sync_count = 0;
|
|
h_sync_count = 0;
|
|
}
|
|
|
|
// Destructor
|
|
VideoOut::~VideoOut()
|
|
{
|
|
|
|
}
|
|
|
|
// evaluate : RGB with synchros
|
|
void VideoOut::eval_RGB_HV
|
|
(
|
|
// Clock
|
|
vluint8_t clk,
|
|
// Synchros
|
|
vluint8_t vs,
|
|
vluint8_t hs,
|
|
// RGB colors
|
|
vluint8_t red,
|
|
vluint8_t green,
|
|
vluint8_t blue
|
|
)
|
|
{
|
|
|
|
// Rising edge on clock
|
|
if (clk && !prev_clk) {
|
|
//printf("\nh stage %d, v stage %d, hs %d (prev:%d), vs %d (prev:%d), hcount %d, vcount %d, hsync_cnt:%d, vsync_cnt:%d\n",
|
|
// h_sync_stage,v_sync_stage,hs,prev_hs,vs,prev_vs,hcount,vcount,h_sync_count,v_sync_count);
|
|
|
|
// Horizontal synch update
|
|
bool h_sync_achieved = false;
|
|
switch (h_sync_stage)
|
|
{
|
|
case e_Front:
|
|
h_sync_count ++;
|
|
if (h_sync_count == hfporch-1) {
|
|
h_sync_stage = e_SynchPulseUp;
|
|
h_sync_count = 0;
|
|
}
|
|
break;
|
|
case e_SynchPulseUp:
|
|
if ((hs == hs_pol) && (prev_hs != hs_pol)) {
|
|
// raising edge on hs
|
|
h_sync_stage = e_SynchPulseDown;
|
|
if (dbg_on) printf(" Rising edge on HS");
|
|
}
|
|
break;
|
|
case e_SynchPulseDown:
|
|
if ((hs != hs_pol) && (prev_hs != hs_pol)) {
|
|
// falling edge on hs
|
|
h_sync_stage = e_Back;
|
|
h_sync_count ++;
|
|
}
|
|
break;
|
|
case e_Back:
|
|
h_sync_count ++;
|
|
if (h_sync_count == hbporch) {
|
|
h_sync_stage = e_Done;
|
|
h_sync_count = 0;
|
|
hcount = 0;
|
|
// just achived hsynch
|
|
h_sync_achieved = true;
|
|
// end of frame?
|
|
if (vcount >= ver_size) {
|
|
// yes, trigger vsynch
|
|
vcount = 0;
|
|
h_sync_stage = e_Front;
|
|
}
|
|
}
|
|
break;
|
|
case e_Done: break;
|
|
}
|
|
|
|
// Vertical synch update, if horizontal synch achieved
|
|
if (h_sync_achieved) {
|
|
|
|
switch (v_sync_stage)
|
|
{
|
|
case e_Front:
|
|
v_sync_count ++;
|
|
if (v_sync_count == vfporch-1) {
|
|
v_sync_stage = e_SynchPulseUp;
|
|
v_sync_count = 0;
|
|
}
|
|
break;
|
|
case e_SynchPulseUp:
|
|
if ((vs == vs_pol) && (prev_vs != vs_pol)) {
|
|
// raising edge on vs
|
|
v_sync_stage = e_SynchPulseDown;
|
|
if (dbg_on) printf(" Rising edge on VS");
|
|
}
|
|
break;
|
|
case e_SynchPulseDown:
|
|
if ((vs != vs_pol) && (prev_vs != vs_pol)) {
|
|
// falling edge on vs
|
|
v_sync_stage = e_Back;
|
|
v_sync_count ++;
|
|
|
|
}
|
|
break;
|
|
case e_Back:
|
|
v_sync_count ++;
|
|
if (v_sync_count == vbporch) {
|
|
vcount = 0;
|
|
v_sync_stage = e_Done;
|
|
v_sync_count = 0;
|
|
{
|
|
char num[64];
|
|
snprintf(num,64, "%04d", dump_ctr);
|
|
std::string tmp = filename + "_" + std::string(num) + ".tga";
|
|
// printf(" Save snapshot in file \"%s\"\n", tmp.c_str());
|
|
{
|
|
ImageRGB img;
|
|
img.pixels() = pixels;
|
|
saveImage(tmp.c_str(),&img);
|
|
}
|
|
dump_ctr++;
|
|
}
|
|
}
|
|
break;
|
|
case e_Done: break;
|
|
}
|
|
|
|
prev_vs = vs;
|
|
|
|
}
|
|
|
|
// reset horizontal synchro
|
|
if (h_sync_stage == e_Done) {
|
|
if (hcount >= hor_size) {
|
|
h_sync_stage = e_Front;
|
|
vcount ++;
|
|
}
|
|
}
|
|
// reset vertical synchro
|
|
if (v_sync_stage == e_Done) {
|
|
if (vcount >= ver_size) {
|
|
h_sync_stage = e_Front;
|
|
v_sync_stage = e_Front;
|
|
}
|
|
}
|
|
|
|
// Grab active area
|
|
if (v_sync_stage == e_Done && h_sync_stage == e_Done) {
|
|
|
|
if (vcount < ver_size) {
|
|
if (hcount < hor_size) {
|
|
|
|
uchar r = (red & bit_mask) << (bit_shift);
|
|
uchar g = (green & bit_mask) << (bit_shift);
|
|
uchar b = (blue & bit_mask) << (bit_shift);
|
|
|
|
if (hcount >= 0 && vcount >= 0 && hcount < pixels.xsize() && vcount < pixels.ysize()) {
|
|
pixels.at((int)(hcount), (int)(vcount)) = v3b(r,g,b);
|
|
// printf("*** [pixel write at %d,%d R%dG%dB%d]\n",hcount,vcount,(int)r,(int)g,(int)b);
|
|
} else {
|
|
printf("*** [ERROR] out of bounds pixel write at %d,%d R%dG%dB%d]\n",hcount,vcount,(int)r,(int)g,(int)b);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
hcount ++;
|
|
|
|
prev_hs = hs;
|
|
|
|
}
|
|
|
|
prev_clk = clk;
|
|
|
|
}
|
|
|
|
vluint16_t VideoOut::get_hcount()
|
|
{
|
|
return hcount;
|
|
}
|
|
|
|
vluint16_t VideoOut::get_vcount()
|
|
{
|
|
return vcount;
|
|
}
|
|
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
// SL 2019-10-09
|
|
|
|
#include "Vtop.h"
|
|
#include <iostream>
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
|
|
Verilated::commandArgs(argc,argv);
|
|
|
|
Vtop *bare_test = new Vtop();
|
|
|
|
char foo[1<<17]; // DEBUG FIXME: there is an access violation that makes this necessary. I have not been able to track it down so far!! Terrible.
|
|
|
|
while (!Verilated::gotFinish()) {
|
|
|
|
bare_test->clk = 1;
|
|
|
|
bare_test->eval();
|
|
|
|
bare_test->clk = 0;
|
|
|
|
bare_test->eval();
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
// SL 2019-09-23
|
|
|
|
#include "Vtop.h"
|
|
#include <iostream>
|
|
|
|
#include "VgaChip.h"
|
|
#include "sdr_sdram.h"
|
|
|
|
unsigned int main_time = 0;
|
|
double sc_time_stamp()
|
|
{
|
|
return main_time;
|
|
}
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
Verilated::commandArgs(argc,argv);
|
|
|
|
Vtop *vga_test = new Vtop();
|
|
|
|
vga_test->clk = 0;
|
|
|
|
// we need to step simulation until we get the parameters
|
|
do {
|
|
|
|
vga_test->clk = 1 - vga_test->clk;
|
|
|
|
vga_test->eval();
|
|
|
|
} while ((int)vga_test->video_color_depth == 0);
|
|
|
|
VgaChip *vga_chip = new VgaChip((int)vga_test->video_color_depth);
|
|
|
|
char foo[1<<18]; // DEBUG FIXME: there is an access violation that makes this necessary. I have not been able to track it down so far!! Terrible.
|
|
|
|
vluint8_t sdram_flags = 0;
|
|
if ((int)vga_test->sdram_word_width == 8) {
|
|
sdram_flags |= FLAG_DATA_WIDTH_8;
|
|
} else if ((int)vga_test->sdram_word_width == 16) {
|
|
sdram_flags |= FLAG_DATA_WIDTH_16;
|
|
} else if ((int)vga_test->sdram_word_width == 32) {
|
|
sdram_flags |= FLAG_DATA_WIDTH_32;
|
|
} else if ((int)vga_test->sdram_word_width == 64) {
|
|
sdram_flags |= FLAG_DATA_WIDTH_64;
|
|
}
|
|
|
|
SDRAM* sdr = new SDRAM(13 /*8192*/, 10 /*1024*/, sdram_flags, NULL);
|
|
// "sdram.txt");
|
|
vluint64_t sdram_dq = 0;
|
|
|
|
vluint8_t prev_vga_vs = 0;
|
|
|
|
while (!Verilated::gotFinish()) {
|
|
|
|
vga_test->clk = 1 - vga_test->clk;
|
|
|
|
vga_test->eval();
|
|
|
|
sdr->eval(main_time,
|
|
vga_test->sdram_clock, 1,
|
|
vga_test->sdram_cs, vga_test->sdram_ras, vga_test->sdram_cas, vga_test->sdram_we,
|
|
vga_test->sdram_ba, vga_test->sdram_a,
|
|
vga_test->sdram_dqm, (vluint64_t)vga_test->sdram_dq_o, sdram_dq);
|
|
|
|
vga_test->sdram_dq_i = (vga_test->sdram_dq_en) ? vga_test->sdram_dq_o : sdram_dq;
|
|
|
|
if (prev_vga_vs == 0 && vga_test->video_vs != 0) {
|
|
static int cnt = 0;
|
|
char str[256];
|
|
snprintf(str,256,"dump_%04d.raw",cnt++);
|
|
sdr->save(str,4*8192*1024*2,0);
|
|
}
|
|
prev_vga_vs = vga_test->video_vs;
|
|
|
|
vga_chip->eval(
|
|
vga_test->video_clock,
|
|
vga_test->video_vs,vga_test->video_hs,
|
|
vga_test->video_r,vga_test->video_g,vga_test->video_b);
|
|
|
|
main_time ++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Copyright 2013 Frederic Requin
|
|
//
|
|
// This file is part of the MCC216 project (www.arcaderetrogaming.com)
|
|
//
|
|
// The SDRAM C++ model is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The SDRAM C++ model is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
// SDRAM C++ model:
|
|
// ----------------
|
|
// - Based on the verilog model from Micron : "mt48lc8m16a2.v" // 2 meg x 16 x 4 banks
|
|
// - Designed to work with "Verilator" tool (www.veripool.org)
|
|
// - 8/16/32-bit data bus supported
|
|
// - 4 banks only
|
|
// - Two memory layouts : interleaved banks or contiguous banks
|
|
// - Sequential burst only, no interleaved burst yet
|
|
// - Binary images can be loaded to and saved from SDRAM
|
|
// - Debug mode to trace every SDRAM access
|
|
// - Endianness support for 16 and 32-bit memories
|
|
//
|
|
// TODO:
|
|
// - Add interleaved burst support
|
|
//
|
|
// 2020-03-03 - included in silice project, Sylvain Lefebvre, @sylefeb
|
|
|
|
#ifndef _SDR_SDRAM_H_
|
|
#define _SDR_SDRAM_H_
|
|
|
|
#include "verilated.h"
|
|
|
|
#define SDRAM_NUM_BANKS (4)
|
|
#define SDRAM_BIT_BANKS (2)
|
|
#define CMD_PIPE_DEPTH (4)
|
|
#define DQM_PIPE_DEPTH (2)
|
|
|
|
#define FLAG_DATA_WIDTH_8 ((vluint8_t)0x00)
|
|
#define FLAG_DATA_WIDTH_16 ((vluint8_t)0x01)
|
|
#define FLAG_DATA_WIDTH_32 ((vluint8_t)0x03)
|
|
#define FLAG_DATA_WIDTH_64 ((vluint8_t)0x07)
|
|
#define FLAG_BANK_INTERLEAVING ((vluint8_t)0x08)
|
|
#define FLAG_BIG_ENDIAN ((vluint8_t)0x10)
|
|
#define FLAG_RANDOM_FILLED ((vluint8_t)0x20)
|
|
#define FLAG_DEBUG_ON ((vluint8_t)0x40)
|
|
|
|
class SDRAM
|
|
{
|
|
public:
|
|
// Constructor and destructor
|
|
SDRAM(vluint8_t log2_rows, vluint8_t log2_cols, vluint8_t flags, char *logfile);
|
|
~SDRAM();
|
|
// Methods
|
|
void load(const char *name, vluint32_t size, vluint32_t addr);
|
|
void save(const char *name, vluint32_t size, vluint32_t addr);
|
|
void eval(vluint64_t ts, vluint8_t clk, vluint8_t cke,
|
|
vluint8_t cs_n, vluint8_t ras_n, vluint8_t cas_n, vluint8_t we_n,
|
|
vluint8_t ba, vluint16_t addr,
|
|
vluint8_t dqm, vluint64_t dq_in, vluint64_t &dq_out);
|
|
vluint8_t read_byte(vluint32_t addr);
|
|
vluint16_t read_word(vluint32_t addr);
|
|
vluint32_t read_long(vluint32_t addr);
|
|
vluint64_t read_quad(vluint32_t addr);
|
|
vluint32_t mem_size;
|
|
private:
|
|
// Byte reading functions (to speedup access)
|
|
vluint8_t (SDRAM::*read_byte_priv)(vluint32_t);
|
|
vluint8_t read_byte_i_be_8(vluint32_t addr);
|
|
vluint8_t read_byte_i_be_16(vluint32_t addr);
|
|
vluint8_t read_byte_i_be_32(vluint32_t addr);
|
|
vluint8_t read_byte_i_be_64(vluint32_t addr);
|
|
vluint8_t read_byte_i_le_8(vluint32_t addr);
|
|
vluint8_t read_byte_i_le_16(vluint32_t addr);
|
|
vluint8_t read_byte_i_le_32(vluint32_t addr);
|
|
vluint8_t read_byte_i_le_64(vluint32_t addr);
|
|
vluint8_t read_byte_c_be_8(vluint32_t addr);
|
|
vluint8_t read_byte_c_be_16(vluint32_t addr);
|
|
vluint8_t read_byte_c_be_32(vluint32_t addr);
|
|
vluint8_t read_byte_c_be_64(vluint32_t addr);
|
|
vluint8_t read_byte_c_le_8(vluint32_t addr);
|
|
vluint8_t read_byte_c_le_16(vluint32_t addr);
|
|
vluint8_t read_byte_c_le_32(vluint32_t addr);
|
|
vluint8_t read_byte_c_le_64(vluint32_t addr);
|
|
// SDRAM capacity
|
|
int bus_mask; // Data bus width (bytes - 1)
|
|
int bus_log2; // Data bus width (log2(bytes))
|
|
int num_rows; // Number of rows
|
|
int num_cols; // Number of columns
|
|
int bit_rows; // Number of rows (log 2)
|
|
int bit_cols; // Number of columns (log 2)
|
|
vluint32_t mask_bank; // Bit mask for banks
|
|
vluint32_t mask_rows; // Bit mask for rows
|
|
vluint32_t mask_cols; // Bit mask for columns
|
|
// Memory arrays
|
|
vluint8_t *mem_array_7[SDRAM_NUM_BANKS]; // MSB
|
|
vluint8_t *mem_array_6[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_5[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_4[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_3[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_2[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_1[SDRAM_NUM_BANKS];
|
|
vluint8_t *mem_array_0[SDRAM_NUM_BANKS]; // LSB
|
|
// Mode register
|
|
int cas_lat; // CAS latency (2 or 3)
|
|
int bst_len_rd; // Burst length during read
|
|
int bst_len_wr; // Burst length during write
|
|
vluint8_t bst_type; // Burst type
|
|
// Debug mode
|
|
vluint8_t dbg_on;
|
|
// Special memory flags
|
|
vluint8_t mem_flags;
|
|
// Internal variables
|
|
vluint8_t prev_clk; // Previous clock state
|
|
vluint8_t cmd_pipe[CMD_PIPE_DEPTH]; // Command pipeline
|
|
int col_pipe[CMD_PIPE_DEPTH]; // Column address pipeline
|
|
vluint8_t ba_pipe[CMD_PIPE_DEPTH]; // Bank address pipeline
|
|
vluint8_t bap_pipe[CMD_PIPE_DEPTH]; // Bank precharge pipeline
|
|
vluint8_t a10_pipe[CMD_PIPE_DEPTH]; // A[10] wire pipeline
|
|
vluint8_t dqm_pipe[DQM_PIPE_DEPTH]; // DQM pipeline (for read)
|
|
vluint8_t row_act[SDRAM_NUM_BANKS]; // Bank activate
|
|
vluint8_t row_pre[SDRAM_NUM_BANKS]; // Bank precharge
|
|
int row_addr[SDRAM_NUM_BANKS]; // Row address during activate
|
|
vluint8_t ap_bank[SDRAM_NUM_BANKS]; // Bank being auto-precharged
|
|
int bank; // Current bank during read/write
|
|
int row; // Current row during read/write
|
|
int col; // Current column during read/write
|
|
int bst_ctr_rd; // Burst counter (read)
|
|
int bst_ctr_wr; // Burst counter (write)
|
|
public:
|
|
// Log file
|
|
FILE *fh_log;
|
|
char *log_buf;
|
|
int log_size;
|
|
};
|
|
|
|
#endif /* _SDR_SDRAM_H_ */
|
|
// Copyright 2013 Frederic Requin
|
|
//
|
|
// This file is part of the MCC216 project (www.arcaderetrogaming.com)
|
|
//
|
|
// The SDRAM C++ model is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The SDRAM C++ model is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
// SDRAM C++ model:
|
|
// ----------------
|
|
// - Based on the verilog model from Micron : "mt48lc8m16a2.v"
|
|
// - Designed to work with "Verilator" tool (www.veripool.org)
|
|
// - 8/16/32-bit data bus supported
|
|
// - 4 banks only
|
|
// - Two memory layouts : interleaved banks or contiguous banks
|
|
// - Sequential burst only, no interleaved burst yet
|
|
// - Binary images can be loaded to and saved from SDRAM
|
|
// - Debug mode to trace every SDRAM access
|
|
// - Endianness support for 16 and 32-bit memories
|
|
//
|
|
// TODO:
|
|
// - Add interleaved burst support
|
|
|
|
#include "verilated.h"
|
|
#include "sdr_sdram.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
#include <iostream>
|
|
|
|
// SDRAM commands
|
|
#define CMD_LMR ((vluint8_t)0)
|
|
#define CMD_REF ((vluint8_t)1)
|
|
#define CMD_PRE ((vluint8_t)2)
|
|
#define CMD_ACT ((vluint8_t)3)
|
|
#define CMD_WR ((vluint8_t)4)
|
|
#define CMD_RD ((vluint8_t)5)
|
|
#define CMD_BST ((vluint8_t)6)
|
|
#define CMD_NOP ((vluint8_t)7)
|
|
|
|
// Data lanes
|
|
#define DATA_MSB ((vluint8_t)0x01)
|
|
#define DATA_MSW ((vluint8_t)0x02)
|
|
#define DATA_MSL ((vluint8_t)0x04)
|
|
|
|
// Constructor
|
|
SDRAM::SDRAM(vluint8_t log2_rows, vluint8_t log2_cols, vluint8_t flags, char *logfile)
|
|
{
|
|
// memory size
|
|
int s = (int)1 << (log2_rows + log2_cols);
|
|
// SDRAM capacity initialized
|
|
bus_mask = flags & (DATA_MSB | DATA_MSW | DATA_MSL);
|
|
bus_log2 = (flags & DATA_MSB) ? 1 : 0;
|
|
bus_log2 = (flags & DATA_MSW) ? 2 : bus_log2;
|
|
bus_log2 = (flags & DATA_MSL) ? 3 : bus_log2;
|
|
bit_rows = (int)log2_rows;
|
|
bit_cols = (int)log2_cols;
|
|
num_rows = (int)1 << log2_rows;
|
|
num_cols = (int)1 << log2_cols;
|
|
mask_cols = (num_cols - 1) << bus_log2;
|
|
if (flags & FLAG_BANK_INTERLEAVING)
|
|
{
|
|
// Banks are interleaved
|
|
mask_rows = (vluint32_t)(num_rows - 1) << (log2_cols + bus_log2 + SDRAM_BIT_BANKS);
|
|
mask_bank = (vluint32_t)(SDRAM_NUM_BANKS - 1) << (log2_cols + bus_log2 );
|
|
}
|
|
else
|
|
{
|
|
// Banks are contiguous
|
|
mask_rows = (vluint32_t)(num_rows - 1) << (log2_cols + bus_log2 );
|
|
mask_bank = (vluint32_t)(SDRAM_NUM_BANKS - 1) << (log2_cols + bus_log2 + SDRAM_BIT_BANKS);
|
|
}
|
|
mem_size = s << (bus_log2 + SDRAM_BIT_BANKS);
|
|
// Init message
|
|
std::cerr << "Instantiating " << (mem_size >> 20) << " MB SDRAM : " << SDRAM_NUM_BANKS << " banks x " << num_rows << " rows x " << num_cols << " cols x " << (8 << bus_log2) << " bits" << std::endl;
|
|
// byte reading function
|
|
switch (flags & (DATA_MSB | DATA_MSW | DATA_MSL | FLAG_BANK_INTERLEAVING | FLAG_BIG_ENDIAN))
|
|
{
|
|
// Little endian, contiguous banks
|
|
case 0x00 : read_byte_priv = &SDRAM::read_byte_c_le_8; break;
|
|
case 0x01 : read_byte_priv = &SDRAM::read_byte_c_le_16; break;
|
|
case 0x02 : read_byte_priv = &SDRAM::read_byte_c_le_32; break;
|
|
case 0x03 : read_byte_priv = &SDRAM::read_byte_c_le_32; break;
|
|
case 0x04 : read_byte_priv = &SDRAM::read_byte_c_le_64; break;
|
|
case 0x05 : read_byte_priv = &SDRAM::read_byte_c_le_64; break;
|
|
case 0x06 : read_byte_priv = &SDRAM::read_byte_c_le_64; break;
|
|
case 0x07 : read_byte_priv = &SDRAM::read_byte_c_le_64; break;
|
|
// Little endian, interleaved banks
|
|
case 0x08 : read_byte_priv = &SDRAM::read_byte_i_le_8; break;
|
|
case 0x09 : read_byte_priv = &SDRAM::read_byte_i_le_16; break;
|
|
case 0x0A : read_byte_priv = &SDRAM::read_byte_i_le_32; break;
|
|
case 0x0B : read_byte_priv = &SDRAM::read_byte_i_le_32; break;
|
|
case 0x0C : read_byte_priv = &SDRAM::read_byte_i_le_64; break;
|
|
case 0x0D : read_byte_priv = &SDRAM::read_byte_i_le_64; break;
|
|
case 0x0E : read_byte_priv = &SDRAM::read_byte_i_le_64; break;
|
|
case 0x0F : read_byte_priv = &SDRAM::read_byte_i_le_64; break;
|
|
// Big endian, contiguous banks
|
|
case 0x10 : read_byte_priv = &SDRAM::read_byte_c_be_8; break;
|
|
case 0x11 : read_byte_priv = &SDRAM::read_byte_c_be_16; break;
|
|
case 0x12 : read_byte_priv = &SDRAM::read_byte_c_be_32; break;
|
|
case 0x13 : read_byte_priv = &SDRAM::read_byte_c_be_32; break;
|
|
case 0x14 : read_byte_priv = &SDRAM::read_byte_c_be_64; break;
|
|
case 0x15 : read_byte_priv = &SDRAM::read_byte_c_be_64; break;
|
|
case 0x16 : read_byte_priv = &SDRAM::read_byte_c_be_64; break;
|
|
case 0x17 : read_byte_priv = &SDRAM::read_byte_c_be_64; break;
|
|
// Big endian, interleaved banks
|
|
case 0x18 : read_byte_priv = &SDRAM::read_byte_i_be_8; break;
|
|
case 0x19 : read_byte_priv = &SDRAM::read_byte_i_be_16; break;
|
|
case 0x1A : read_byte_priv = &SDRAM::read_byte_i_be_32; break;
|
|
case 0x1B : read_byte_priv = &SDRAM::read_byte_i_be_32; break;
|
|
case 0x1C : read_byte_priv = &SDRAM::read_byte_i_be_64; break;
|
|
case 0x1D : read_byte_priv = &SDRAM::read_byte_i_be_64; break;
|
|
case 0x1E : read_byte_priv = &SDRAM::read_byte_i_be_64; break;
|
|
case 0x1F : read_byte_priv = &SDRAM::read_byte_i_be_64; break;
|
|
}
|
|
|
|
// debug mode
|
|
if (logfile)
|
|
{
|
|
fh_log = fopen(logfile, "w");
|
|
log_buf = new char[2048];
|
|
log_size = 0;
|
|
if ((fh_log) && (log_buf))
|
|
{
|
|
printf("SDRAM log file \"%s\" created\n", logfile);
|
|
dbg_on = 1;
|
|
}
|
|
else
|
|
{
|
|
dbg_on = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fh_log = (FILE *)NULL;
|
|
log_buf = (char *)NULL;
|
|
log_size = 0;
|
|
dbg_on = 0;
|
|
}
|
|
|
|
// special flags
|
|
mem_flags = flags;
|
|
|
|
// mode register cleared
|
|
cas_lat = 0;
|
|
bst_len_rd = (int)0;
|
|
bst_len_wr = (int)0;
|
|
bst_type = (vluint8_t)0;
|
|
|
|
// internal variables cleared
|
|
prev_clk = (vluint8_t)0;
|
|
for (int i = 0; i < CMD_PIPE_DEPTH; i++)
|
|
{
|
|
cmd_pipe[i] = CMD_NOP;
|
|
col_pipe[i] = (int)0;
|
|
ba_pipe[i] = (vluint8_t)0;
|
|
bap_pipe[i] = (vluint8_t)0;
|
|
a10_pipe[i] = (vluint16_t)0;
|
|
}
|
|
dqm_pipe[0] = (vluint8_t)0;
|
|
dqm_pipe[1] = (vluint8_t)0;
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
row_act[i] = (vluint8_t)1;
|
|
row_pre[i] = (vluint8_t)0;
|
|
row_addr[i] = (int)0;
|
|
ap_bank[i] = (vluint8_t)0;
|
|
}
|
|
bank = (int)0;
|
|
row = (int)0;
|
|
col = (int)0;
|
|
bst_ctr_rd = (int)0;
|
|
bst_ctr_wr = (int)0;
|
|
|
|
// one array per byte lane and per bank (up to 16 arrays)
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
mem_array_0[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSB) mem_array_1[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSW) mem_array_2[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSW) mem_array_3[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSL) mem_array_4[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSL) mem_array_5[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSL) mem_array_6[i] = new vluint8_t[s];
|
|
if (flags & DATA_MSL) mem_array_7[i] = new vluint8_t[s];
|
|
}
|
|
|
|
if (flags & FLAG_RANDOM_FILLED)
|
|
{
|
|
// fill the arrays with random numbers
|
|
srand (time (NULL));
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
for (int j = 0; j < s; j++)
|
|
{
|
|
mem_array_0[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSB) mem_array_1[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSW) mem_array_2[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSW) mem_array_3[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSL) mem_array_4[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSL) mem_array_5[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSL) mem_array_6[i][j] = (vluint8_t)rand() & 0xFF;
|
|
if (flags & DATA_MSL) mem_array_7[i][j] = (vluint8_t)rand() & 0xFF;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// clear the arrays
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
for (int j = 0; j < s; j++)
|
|
{
|
|
mem_array_0[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSB) mem_array_1[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSW) mem_array_2[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSW) mem_array_3[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSL) mem_array_4[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSL) mem_array_5[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSL) mem_array_6[i][j] = (vluint8_t)0;
|
|
if (flags & DATA_MSL) mem_array_7[i][j] = (vluint8_t)0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Destructor
|
|
SDRAM::~SDRAM()
|
|
{
|
|
// free the memory
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
delete[] mem_array_0[i];
|
|
if (mem_flags & DATA_MSB) delete[] mem_array_1[i];
|
|
if (mem_flags & DATA_MSW) delete[] mem_array_2[i];
|
|
if (mem_flags & DATA_MSW) delete[] mem_array_3[i];
|
|
if (mem_flags & DATA_MSL) delete[] mem_array_4[i];
|
|
if (mem_flags & DATA_MSL) delete[] mem_array_5[i];
|
|
if (mem_flags & DATA_MSL) delete[] mem_array_6[i];
|
|
if (mem_flags & DATA_MSL) delete[] mem_array_7[i];
|
|
}
|
|
}
|
|
|
|
// Binary file loading
|
|
void SDRAM::load(const char *name, vluint32_t size, vluint32_t addr)
|
|
{
|
|
FILE *fh;
|
|
|
|
fh = fopen(name, "rb");
|
|
if (fh)
|
|
{
|
|
int row_size; // Row size (num_cols * 1, 2 or 4)
|
|
vluint8_t *row_buf; // Row buffer
|
|
int row_pos; // Row position (0 to num_rows - 1)
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
// Row size computation based on data bus width
|
|
row_size = (int)1 << (bit_cols + bus_log2);
|
|
// Allocate one full row
|
|
row_buf = new vluint8_t[row_size];
|
|
|
|
// Row position
|
|
row_pos = (int)addr >> (bit_cols + bus_log2);
|
|
// Banks layout
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
{
|
|
// Banks are interleaved
|
|
bank_nr = row_pos & (SDRAM_NUM_BANKS - 1);
|
|
row_pos = row_pos >> SDRAM_BIT_BANKS;
|
|
}
|
|
else
|
|
{
|
|
// Banks are contiguous
|
|
bank_nr = row_pos >> bit_rows;
|
|
row_pos = row_pos & (num_rows - 1);
|
|
}
|
|
idx = row_pos << bit_cols;
|
|
|
|
printf("Starting row : %d, starting bank : %d\n", row_pos, bank_nr);
|
|
printf("Loading 0x%08lX bytes @ 0x%08lX from binary file \"%s\"...", size, addr, name);
|
|
for (int i = 0; i < (int)size; i += row_size)
|
|
{
|
|
// Read one full row from the binary file
|
|
fread((void *)row_buf, row_size, 1, fh);
|
|
|
|
// Here, we take care of the endianness
|
|
if (mem_flags & FLAG_BIG_ENDIAN)
|
|
{
|
|
// MSB first (motorola's way)
|
|
for (int j = 0; j < row_size; )
|
|
{
|
|
// Write MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
mem_array_7[bank_nr][idx] = row_buf[j++];
|
|
mem_array_6[bank_nr][idx] = row_buf[j++];
|
|
mem_array_5[bank_nr][idx] = row_buf[j++];
|
|
mem_array_4[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Write MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
mem_array_3[bank_nr][idx] = row_buf[j++];
|
|
mem_array_2[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Write MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
mem_array_1[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Write LSB
|
|
mem_array_0[bank_nr][idx] = row_buf[j++];
|
|
// Next word
|
|
idx++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// LSB first (intel's way)
|
|
for (int j = 0; j < row_size; )
|
|
{
|
|
// Write LSB
|
|
mem_array_0[bank_nr][idx] = row_buf[j++];
|
|
// Write MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
mem_array_1[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Write MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
mem_array_2[bank_nr][idx] = row_buf[j++];
|
|
mem_array_3[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Write MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
mem_array_4[bank_nr][idx] = row_buf[j++];
|
|
mem_array_5[bank_nr][idx] = row_buf[j++];
|
|
mem_array_6[bank_nr][idx] = row_buf[j++];
|
|
mem_array_7[bank_nr][idx] = row_buf[j++];
|
|
}
|
|
// Next word
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
// Compute next row's address
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
{
|
|
// Increment bank number
|
|
bank_nr = (bank_nr + 1) & (SDRAM_NUM_BANKS - 1);
|
|
|
|
// Bank #3 -> bank #0
|
|
if (!bank_nr)
|
|
{
|
|
row_pos ++;
|
|
if ((row_pos == (int)num_rows) && ((i + row_size) < (int)size))
|
|
{
|
|
printf("Memory overflow while loading !!\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
idx -= (int)num_cols;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Increment row position
|
|
row_pos = (row_pos + 1) & ((int)num_rows - 1);
|
|
|
|
// Last row in a bank
|
|
if (!row_pos)
|
|
{
|
|
idx = 0;
|
|
bank_nr++;
|
|
if ((bank_nr == SDRAM_NUM_BANKS) && ((i + row_size) < (int)size))
|
|
{
|
|
printf("Memory overflow while loading !!\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("OK\n");
|
|
|
|
delete[] row_buf;
|
|
}
|
|
else
|
|
{
|
|
printf("Cannot load binary file \"%s\" !!\n", name);
|
|
}
|
|
}
|
|
|
|
// Binary file saving
|
|
void SDRAM::save(const char *name, vluint32_t size, vluint32_t addr)
|
|
{
|
|
FILE *fh;
|
|
|
|
fh = fopen(name, "wb");
|
|
if (fh)
|
|
{
|
|
int row_size; // Row size (num_cols * 1, 2 or 4)
|
|
vluint8_t *row_buf; // Row buffer
|
|
int row_pos; // Row position (0 to num_rows - 1)
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
// Row size computation based on data bus width
|
|
row_size = (int)1 << (bit_cols + bus_log2);
|
|
// Allocate one full row
|
|
row_buf = new vluint8_t[row_size];
|
|
|
|
// Row position
|
|
row_pos = (int)addr >> (bus_log2 + bit_cols);
|
|
// Banks layout
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
{
|
|
// Banks are interleaved
|
|
bank_nr = row_pos & (SDRAM_NUM_BANKS - 1);
|
|
row_pos = row_pos >> SDRAM_BIT_BANKS;
|
|
}
|
|
else
|
|
{
|
|
// Banks are contiguous
|
|
bank_nr = row_pos >> bit_rows;
|
|
row_pos = row_pos & (num_rows - 1);
|
|
}
|
|
idx = row_pos << bit_cols;
|
|
|
|
printf("Saving 0x%08lX bytes @ 0x%08lX to binary file \"%s\"...", size, addr, name);
|
|
for (int i = 0; i < (int)size; i += row_size)
|
|
{
|
|
// Here, we take care of the endianness
|
|
if (mem_flags & FLAG_BIG_ENDIAN)
|
|
{
|
|
// MSB first (motorola's way)
|
|
for (int j = 0; j < row_size; )
|
|
{
|
|
// Read MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
row_buf[j++] = mem_array_7[bank_nr][idx];
|
|
row_buf[j++] = mem_array_6[bank_nr][idx];
|
|
row_buf[j++] = mem_array_5[bank_nr][idx];
|
|
row_buf[j++] = mem_array_4[bank_nr][idx];
|
|
}
|
|
// Read MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
row_buf[j++] = mem_array_3[bank_nr][idx];
|
|
row_buf[j++] = mem_array_2[bank_nr][idx];
|
|
}
|
|
// Read MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
row_buf[j++] = mem_array_1[bank_nr][idx];
|
|
}
|
|
// Read LSB
|
|
row_buf[j++] = mem_array_0[bank_nr][idx];
|
|
// Next word
|
|
idx++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// LSB first (intel's way)
|
|
for (int j = 0; j < row_size; )
|
|
{
|
|
// Read LSB
|
|
row_buf[j++] = mem_array_0[bank_nr][idx];
|
|
// Read MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
row_buf[j++] = mem_array_1[bank_nr][idx];
|
|
}
|
|
// Read MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
row_buf[j++] = mem_array_2[bank_nr][idx];
|
|
row_buf[j++] = mem_array_3[bank_nr][idx];
|
|
}
|
|
// Read MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
row_buf[j++] = mem_array_4[bank_nr][idx];
|
|
row_buf[j++] = mem_array_5[bank_nr][idx];
|
|
row_buf[j++] = mem_array_6[bank_nr][idx];
|
|
row_buf[j++] = mem_array_7[bank_nr][idx];
|
|
}
|
|
// Next word
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
// Compute next row's address
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
{
|
|
// Increment bank number
|
|
bank_nr = (bank_nr + 1) & (SDRAM_NUM_BANKS - 1);
|
|
|
|
// Bank #3 -> bank #0
|
|
if (!bank_nr)
|
|
{
|
|
row_pos ++;
|
|
if ((row_pos == (int)num_rows) && ((i + row_size) < (int)size))
|
|
{
|
|
printf("Memory overflow while saving !!\n");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
idx -= (int)num_cols;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Increment row position
|
|
row_pos = (row_pos + 1) & ((int)num_rows - 1);
|
|
|
|
// Last row in a bank
|
|
if (!row_pos)
|
|
{
|
|
idx = 0;
|
|
bank_nr++;
|
|
if ((bank_nr == SDRAM_NUM_BANKS) && ((i + row_size) < (int)size))
|
|
{
|
|
printf("Memory overflow while saving !!\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write one full row to the binary file
|
|
fwrite((void *)row_buf, row_size, 1, fh);
|
|
}
|
|
printf("OK\n");
|
|
|
|
delete[] row_buf;
|
|
fclose(fh);
|
|
}
|
|
else
|
|
{
|
|
printf("Cannot save binary file \"%s\" !!\n", name);
|
|
}
|
|
}
|
|
|
|
// Read a byte
|
|
vluint8_t SDRAM::read_byte(vluint32_t addr)
|
|
{
|
|
return (this->*read_byte_priv)(addr);
|
|
}
|
|
|
|
// Read a word
|
|
vluint16_t SDRAM::read_word(vluint32_t addr)
|
|
{
|
|
if (mem_flags & FLAG_BIG_ENDIAN)
|
|
{
|
|
return ((vluint16_t)(this->*read_byte_priv)(addr ) << 8) |
|
|
(vluint16_t)(this->*read_byte_priv)(addr + 1);
|
|
}
|
|
else
|
|
{
|
|
return ((vluint16_t)(this->*read_byte_priv)(addr + 1) << 8) |
|
|
(vluint16_t)(this->*read_byte_priv)(addr );
|
|
}
|
|
}
|
|
|
|
// Read a long
|
|
vluint32_t SDRAM::read_long(vluint32_t addr)
|
|
{
|
|
if (mem_flags & FLAG_BIG_ENDIAN)
|
|
{
|
|
return ((vluint32_t)(this->*read_byte_priv)(addr ) << 24) |
|
|
((vluint32_t)(this->*read_byte_priv)(addr + 1) << 16) |
|
|
((vluint32_t)(this->*read_byte_priv)(addr + 2) << 8) |
|
|
(vluint32_t)(this->*read_byte_priv)(addr + 3);
|
|
}
|
|
else
|
|
{
|
|
return ((vluint32_t)(this->*read_byte_priv)(addr + 3) << 24) |
|
|
((vluint32_t)(this->*read_byte_priv)(addr + 2) << 16) |
|
|
((vluint32_t)(this->*read_byte_priv)(addr + 1) << 8) |
|
|
(vluint32_t)(this->*read_byte_priv)(addr );
|
|
}
|
|
}
|
|
|
|
// Read a quad
|
|
vluint64_t SDRAM::read_quad(vluint32_t addr)
|
|
{
|
|
if (mem_flags & FLAG_BIG_ENDIAN)
|
|
{
|
|
return ((vluint64_t)(this->*read_byte_priv)(addr ) << 56) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 48) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 40) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 32) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 24) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 16) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 8) |
|
|
(vluint64_t)(this->*read_byte_priv)(addr + 3);
|
|
}
|
|
else
|
|
{
|
|
return ((vluint64_t)(this->*read_byte_priv)(addr + 3) << 56) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 48) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 40) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 32) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 24) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 2) << 16) |
|
|
((vluint64_t)(this->*read_byte_priv)(addr + 1) << 8) |
|
|
(vluint64_t)(this->*read_byte_priv)(addr );
|
|
}
|
|
}
|
|
|
|
// Cycle evaluate
|
|
void SDRAM::eval
|
|
(
|
|
vluint64_t ts,
|
|
// Clock
|
|
vluint8_t clk,
|
|
vluint8_t cke,
|
|
// Commands
|
|
vluint8_t cs_n,
|
|
vluint8_t ras_n,
|
|
vluint8_t cas_n,
|
|
vluint8_t we_n,
|
|
// Address
|
|
vluint8_t ba,
|
|
vluint16_t addr,
|
|
// Data
|
|
vluint8_t dqm,
|
|
vluint64_t dq_in,
|
|
vluint64_t &dq_out
|
|
)
|
|
{
|
|
// Clock enabled
|
|
if (cke)
|
|
{
|
|
// Rising edge on clock
|
|
if (clk && !(prev_clk))
|
|
{
|
|
vluint8_t cmd;
|
|
vluint8_t a10;
|
|
|
|
// Decode SDRAM command
|
|
if (!cs_n)
|
|
cmd = (ras_n << 2) | (cas_n << 1) | we_n;
|
|
else
|
|
cmd = CMD_NOP;
|
|
|
|
// A[10] wire
|
|
a10 = (vluint8_t)((addr >> 10) & 1);
|
|
// Mask out extra bits
|
|
ba &= (SDRAM_NUM_BANKS - 1);
|
|
|
|
// Command pipeline
|
|
for (int i = 0; i < CMD_PIPE_DEPTH; i++)
|
|
{
|
|
if (i == (CMD_PIPE_DEPTH - 1))
|
|
{
|
|
cmd_pipe[i] = CMD_NOP;
|
|
col_pipe[i] = (int)0;
|
|
ba_pipe[i] = (vluint8_t)0;
|
|
bap_pipe[i] = (vluint8_t)0;
|
|
a10_pipe[i] = (vluint16_t)0;
|
|
}
|
|
else
|
|
{
|
|
cmd_pipe[i] = cmd_pipe[i+1];
|
|
col_pipe[i] = col_pipe[i+1];
|
|
ba_pipe[i] = ba_pipe[i+1];
|
|
bap_pipe[i] = bap_pipe[i+1];
|
|
a10_pipe[i] = a10_pipe[i+1];
|
|
}
|
|
}
|
|
|
|
// DQM pipeline
|
|
dqm_pipe[0] = dqm_pipe[1];
|
|
dqm_pipe[1] = dqm;
|
|
|
|
// Process SDRAM command (immediate)
|
|
switch (cmd)
|
|
{
|
|
// 000 : Load mode register
|
|
case CMD_LMR:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Load Std Mode Register @ %llu ps\n", ts);
|
|
log_size += sprintf(log_buf + log_size, "Load Std Mode Register @ %llu ps\n", ts);
|
|
}
|
|
|
|
// CAS latency
|
|
switch((addr >> 4) & 7)
|
|
{
|
|
case 2:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("CAS latency = 2 cycles\n");
|
|
log_size += sprintf(log_buf + log_size, "CAS latency = 2 cycles\n");
|
|
}
|
|
cas_lat = (int)2;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("CAS latency = 3 cycles\n");
|
|
log_size += sprintf(log_buf + log_size, "CAS latency = 3 cycles\n");
|
|
}
|
|
cas_lat = (int)3;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("CAS latency = ???\n");
|
|
log_size += sprintf(log_buf + log_size, "CAS latency = ???\n");
|
|
}
|
|
cas_lat = (int)0; // This disables pipelined commands
|
|
}
|
|
}
|
|
|
|
// Burst length
|
|
switch (addr & 7)
|
|
{
|
|
case 0:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = 1 word\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = 1 word\n");
|
|
}
|
|
bst_len_rd = (int)1;
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = 2 words\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = 2 words\n");
|
|
}
|
|
bst_len_rd = (int)2;
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = 4 words\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = 4 words\n");
|
|
}
|
|
bst_len_rd = (int)4;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = 8 words\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = 8 words\n");
|
|
}
|
|
bst_len_rd = (int)8;
|
|
break;
|
|
}
|
|
case 7:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = continuous\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = continuous\n");
|
|
}
|
|
bst_len_rd = (int)num_cols;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Read burst length = ???\n");
|
|
log_size += sprintf(log_buf + log_size, "Read burst length = ???\n");
|
|
}
|
|
bst_len_rd = (int)0; // This will disable burst read
|
|
}
|
|
}
|
|
|
|
// Burst type
|
|
if (addr & 8)
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Burst type = interleaved (NOT SUPPORTED !)\n");
|
|
log_size += sprintf(log_buf + log_size, "Burst type = interleaved (NOT SUPPORTED !)\n");
|
|
}
|
|
bst_type = (vluint8_t)1;
|
|
}
|
|
else
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Burst type = sequential\n");
|
|
log_size += sprintf(log_buf + log_size, "Burst type = sequential\n");
|
|
}
|
|
bst_type = (vluint8_t)0;
|
|
}
|
|
|
|
// Write burst
|
|
if (addr & 0x200)
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
printf("Write burst length = 1\n");
|
|
log_size += sprintf(log_buf + log_size, "Write burst length = 1\n");
|
|
}
|
|
bst_len_wr = (int)1;
|
|
}
|
|
else
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
if (bst_len_rd)
|
|
{
|
|
if (bst_len_rd <= (int)8)
|
|
{
|
|
printf("Write burst length = %d word(s)\n", bst_len_rd);
|
|
log_size += sprintf(log_buf + log_size, "Write burst length = %d word(s)\n", bst_len_rd);
|
|
}
|
|
else
|
|
{
|
|
printf("Write burst length = continuous\n");
|
|
log_size += sprintf(log_buf + log_size, "Write burst length = continuous\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This disables burst write
|
|
printf("Write burst length = ???\n");
|
|
log_size += sprintf(log_buf + log_size, "Write burst length = ???\n");
|
|
}
|
|
}
|
|
bst_len_wr = bst_len_rd;
|
|
}
|
|
break;
|
|
}
|
|
// 001 : Auto refresh
|
|
case CMD_REF:
|
|
{
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Auto Refresh @ %llu ps\n", ts);
|
|
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
if (!row_pre[i])
|
|
{
|
|
printf("ERROR @ %llu ps : All banks must be Precharge before Auto Refresh\n", ts);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
// 010 : Precharge
|
|
case CMD_PRE:
|
|
{
|
|
if (a10)
|
|
{
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Precharge all banks @ %llu ps\n", ts);
|
|
|
|
if (ap_bank[0] || ap_bank[1] || ap_bank[2] || ap_bank[3])
|
|
{
|
|
printf("ERROR @ %llu ps : at least one bank is auto-precharged !\n", ts);
|
|
break;
|
|
}
|
|
|
|
// Precharge all banks
|
|
for (int i = 0; i < SDRAM_NUM_BANKS; i++)
|
|
{
|
|
row_act[i] = 0;
|
|
row_pre[i] = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Precharge bank #%d @ %llu ps\n", ba, ts);
|
|
|
|
if (ap_bank[ba])
|
|
{
|
|
printf("ERROR @ %llu ps : cannot apply a precharge to auto-precharged bank %d !\n", ts, ba);
|
|
break;
|
|
}
|
|
|
|
// Precharge one bank
|
|
row_act[ba] = 0;
|
|
row_pre[ba] = 1;
|
|
}
|
|
|
|
// Terminate a WRITE immediately
|
|
if ((a10) || (bank == (int)ba))
|
|
bst_ctr_wr = 0;
|
|
|
|
// CAS latency pipeline for READ
|
|
if (cas_lat)
|
|
{
|
|
cmd_pipe[cas_lat] = CMD_PRE;
|
|
bap_pipe[cas_lat] = ba;
|
|
a10_pipe[cas_lat] = a10;
|
|
}
|
|
|
|
break;
|
|
}
|
|
// 011 : Activate
|
|
case CMD_ACT:
|
|
{
|
|
// Mask out extra bits
|
|
addr &= (num_rows - 1);
|
|
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Activate bank #%d, row #%d @ %llu ps\n", ba, addr, ts);
|
|
|
|
if (row_act[ba])
|
|
{
|
|
printf("ERROR @ %llu ps : bank %d already active !\n", ts, ba);
|
|
break;
|
|
}
|
|
|
|
row_act[ba] = 1;
|
|
row_pre[ba] = 0;
|
|
row_addr[ba] = (int)addr << bit_cols;
|
|
|
|
break;
|
|
}
|
|
// 100 : Write
|
|
case CMD_WR:
|
|
{
|
|
// Mask out extra bits
|
|
addr &= (mask_cols >> bus_log2);
|
|
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Write bank #%d, col #%d @ %llu ps\n", ba, addr, ts);
|
|
|
|
if (!row_act[ba])
|
|
{
|
|
printf("ERROR @ %llu ps : bank %d is not activated for WRITE !\n", ts, ba);
|
|
break;
|
|
}
|
|
|
|
// Latch command right away
|
|
cmd_pipe[0] = CMD_WR;
|
|
col_pipe[0] = (int)addr;
|
|
ba_pipe[0] = ba;
|
|
|
|
// Auto-precharge
|
|
ap_bank[ba] = a10;
|
|
|
|
break;
|
|
}
|
|
// 101 : Read
|
|
case CMD_RD:
|
|
{
|
|
// Mask out extra bits
|
|
addr &= (mask_cols >> bus_log2);
|
|
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Read bank #%d, col #%d @ %llu ps\n", ba, addr, ts);
|
|
|
|
if (!row_act[ba])
|
|
{
|
|
printf("ERROR @ %llu ps : bank %d is not activated for READ !\n", ts, ba);
|
|
break;
|
|
}
|
|
|
|
// CAS latency pipeline
|
|
if (cas_lat)
|
|
{
|
|
cmd_pipe[cas_lat] = CMD_RD;
|
|
col_pipe[cas_lat] = (int)addr;
|
|
ba_pipe[cas_lat] = ba;
|
|
}
|
|
|
|
// Auto-precharge
|
|
ap_bank[ba] = a10;
|
|
|
|
break;
|
|
}
|
|
// 110 : Burst stop
|
|
case CMD_BST:
|
|
{
|
|
if (dbg_on)
|
|
log_size += sprintf(log_buf + log_size, "Burst Stop bank #%d @ %llu ps\n", ba, ts);
|
|
|
|
if (ap_bank[ba])
|
|
{
|
|
printf("ERROR @ %llu ps : cannot apply a burst stop to auto-precharged bank %d !\n", ts, ba);
|
|
break;
|
|
}
|
|
|
|
// Terminate a WRITE immediately
|
|
bst_ctr_wr = (vluint16_t)0;
|
|
|
|
// CAS latency for READ
|
|
if (cas_lat)
|
|
{
|
|
cmd_pipe[cas_lat] = CMD_BST;
|
|
}
|
|
break;
|
|
}
|
|
// 111 : No operation
|
|
default: ;
|
|
}
|
|
|
|
// Process SDRAM command (pipelined)
|
|
switch (cmd_pipe[0])
|
|
{
|
|
// 010 : Precharge
|
|
case CMD_PRE:
|
|
{
|
|
if ((a10_pipe[0]) || (bap_pipe[0] == (vluint8_t)bank))
|
|
bst_ctr_rd = (int)0;
|
|
break;
|
|
}
|
|
// 100 : Write
|
|
case CMD_WR:
|
|
{
|
|
// Bank, row and column addresses in memory array
|
|
bank = (int)ba_pipe[0];
|
|
row = row_addr[bank] + (col_pipe[0] & ~(bst_len_wr - 1));
|
|
col = col_pipe[0] & (bst_len_wr - 1);
|
|
bst_ctr_rd = (int)0;
|
|
bst_ctr_wr = bst_len_wr;
|
|
|
|
if (dbg_on)
|
|
{
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
fprintf(fh_log, "%08X : ", ((row_addr[bank] << SDRAM_BIT_BANKS) + (bank << bit_cols) + col_pipe[0]) << bus_log2);
|
|
else
|
|
fprintf(fh_log, "%08X : ", (row_addr[bank] + (bank << (bit_rows + bit_cols)) + col_pipe[0]) << bus_log2);
|
|
}
|
|
|
|
break;
|
|
}
|
|
// 101 : Read
|
|
case CMD_RD:
|
|
{
|
|
if (dbg_on)
|
|
{
|
|
if (bst_ctr_rd) fprintf(fh_log, "\n");
|
|
if (log_size) fprintf(fh_log, log_buf);
|
|
log_size = 0;
|
|
}
|
|
|
|
// Bank, row and column addresses in memory array
|
|
bank = (int)ba_pipe[0];
|
|
row = row_addr[bank] + (col_pipe[0] & ~(bst_len_rd - 1));
|
|
col = col_pipe[0] & (bst_len_rd - 1);
|
|
bst_ctr_rd = bst_len_rd;
|
|
bst_ctr_wr = (int)0;
|
|
|
|
if (dbg_on)
|
|
{
|
|
if (mem_flags & FLAG_BANK_INTERLEAVING)
|
|
fprintf(fh_log, "%08X : ", ((row_addr[bank] << SDRAM_BIT_BANKS) + (bank << bit_cols) + col_pipe[0]) << bus_log2);
|
|
else
|
|
fprintf(fh_log, "%08X : ", (row_addr[bank] + (bank << (bit_rows + bit_cols)) + col_pipe[0]) << bus_log2);
|
|
}
|
|
|
|
break;
|
|
}
|
|
// 110 : Burst stop
|
|
case CMD_BST:
|
|
{
|
|
bst_ctr_rd = (int)0;
|
|
break;
|
|
}
|
|
// 111 : No operation
|
|
default: ;
|
|
}
|
|
|
|
// Write to memory
|
|
if (bst_ctr_wr)
|
|
{
|
|
// Write MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
if (dqm & 0x80)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_7[bank][row + col] = (vluint8_t)(dq_in >> 56);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_7[bank][row + col]);
|
|
}
|
|
if (dqm & 0x40)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_6[bank][row + col] = (vluint8_t)(dq_in >> 48);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_6[bank][row + col]);
|
|
}
|
|
if (dqm & 0x20)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_5[bank][row + col] = (vluint8_t)(dq_in >> 40);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_5[bank][row + col]);
|
|
}
|
|
if (dqm & 0x10)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_4[bank][row + col] = (vluint8_t)(dq_in >> 32);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_4[bank][row + col]);
|
|
}
|
|
}
|
|
// Write MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
if (dqm & 0x08)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_3[bank][row + col] = (vluint8_t)(dq_in >> 24);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_3[bank][row + col]);
|
|
}
|
|
if (dqm & 0x04)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_2[bank][row + col] = (vluint8_t)(dq_in >> 16);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_2[bank][row + col]);
|
|
}
|
|
}
|
|
// Write MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
if (dqm & 0x02)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
mem_array_1[bank][row + col] = (vluint8_t)(dq_in >> 8);
|
|
if (dbg_on) fprintf(fh_log, "%02X", mem_array_1[bank][row + col]);
|
|
}
|
|
}
|
|
// Write LSB
|
|
if (dqm & 0x01)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX ");
|
|
}
|
|
else
|
|
{
|
|
mem_array_0[bank][row + col] = (vluint8_t)dq_in;
|
|
if (dbg_on) fprintf(fh_log, "%02X ", mem_array_0[bank][row + col]);
|
|
}
|
|
|
|
// Burst counter (only sequential burst supported)
|
|
col = (col + 1) & (bst_len_wr - 1);
|
|
bst_ctr_wr--;
|
|
|
|
// End of burst
|
|
if (bst_ctr_wr == (int)0)
|
|
{
|
|
// Auto-precharge case
|
|
if (ap_bank[bank])
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "PRE\n\n");
|
|
ap_bank[bank] = (vluint8_t)0;
|
|
row_act[bank] = (vluint8_t)0;
|
|
row_pre[bank] = (vluint8_t)1;
|
|
}
|
|
else
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "\n");
|
|
}
|
|
if (log_size)
|
|
{
|
|
fprintf(fh_log, log_buf);
|
|
log_size = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read from memory
|
|
if (bst_ctr_rd)
|
|
{
|
|
vluint8_t dq_tmp[8];
|
|
|
|
dq_tmp[7] = (vluint8_t)0x00;
|
|
dq_tmp[6] = (vluint8_t)0x00;
|
|
dq_tmp[5] = (vluint8_t)0x00;
|
|
dq_tmp[4] = (vluint8_t)0x00;
|
|
dq_tmp[3] = (vluint8_t)0x00;
|
|
dq_tmp[2] = (vluint8_t)0x00;
|
|
dq_tmp[1] = (vluint8_t)0x00;
|
|
dq_tmp[0] = (vluint8_t)0x00;
|
|
|
|
// Read MSL (if present)
|
|
if (mem_flags & DATA_MSL)
|
|
{
|
|
if (dqm_pipe[0] & 0x80)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[7] = mem_array_7[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[7]);
|
|
}
|
|
if (dqm_pipe[0] & 0x40)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[6] = mem_array_6[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[6]);
|
|
}
|
|
if (dqm_pipe[0] & 0x20)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[5] = mem_array_5[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[5]);
|
|
}
|
|
if (dqm_pipe[0] & 0x10)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[4] = mem_array_4[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[4]);
|
|
}
|
|
}
|
|
|
|
// Read MSW (if present)
|
|
if (mem_flags & DATA_MSW)
|
|
{
|
|
if (dqm_pipe[0] & 0x08)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[3] = mem_array_3[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[3]);
|
|
}
|
|
if (dqm_pipe[0] & 0x04)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[2] = mem_array_2[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[2]);
|
|
}
|
|
}
|
|
|
|
// Read MSB (if present)
|
|
if (mem_flags & DATA_MSB)
|
|
{
|
|
if (dqm_pipe[0] & 0x02)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[1] = mem_array_1[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X", dq_tmp[1]);
|
|
}
|
|
}
|
|
|
|
// Read LSB
|
|
if (dqm_pipe[0] & 0x01)
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "XX ");
|
|
}
|
|
else
|
|
{
|
|
dq_tmp[0] = mem_array_0[bank][row + col];
|
|
if (dbg_on) fprintf(fh_log, "%02X ", dq_tmp[0]);
|
|
}
|
|
|
|
dq_out = ((vluint64_t)dq_tmp[0] )
|
|
| ((vluint64_t)dq_tmp[1] << 8 )
|
|
| ((vluint64_t)dq_tmp[2] << 16)
|
|
| ((vluint64_t)dq_tmp[3] << 24)
|
|
| ((vluint64_t)dq_tmp[4] << 32)
|
|
| ((vluint64_t)dq_tmp[5] << 40)
|
|
| ((vluint64_t)dq_tmp[6] << 48)
|
|
| ((vluint64_t)dq_tmp[7] << 56);
|
|
|
|
// Burst counter (only sequential supported)
|
|
col = (col + 1) & (bst_len_rd - 1);
|
|
bst_ctr_rd--;
|
|
|
|
// End of burst
|
|
if (bst_ctr_rd == (int)0)
|
|
{
|
|
// Auto-precharge case
|
|
if (ap_bank[bank])
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "PRE\n");
|
|
ap_bank[bank] = (vluint8_t)0;
|
|
row_act[bank] = (vluint8_t)0;
|
|
row_pre[bank] = (vluint8_t)1;
|
|
}
|
|
else
|
|
{
|
|
if (dbg_on) fprintf(fh_log, "\n");
|
|
}
|
|
if (log_size)
|
|
{
|
|
fprintf(fh_log, log_buf);
|
|
log_size = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((bst_ctr_wr == (int)0) && (bst_ctr_rd == (int)0) && (log_size != (int)0))
|
|
{
|
|
fprintf(fh_log, log_buf);
|
|
log_size = 0;
|
|
}
|
|
|
|
// For edge detection
|
|
prev_clk = clk;
|
|
}
|
|
// Clock disabled
|
|
else
|
|
{
|
|
prev_clk = (vluint8_t)0;
|
|
}
|
|
}
|
|
|
|
// Read a byte, interleaved banks, big endian, 8-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_be_8(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> bit_cols;
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS));
|
|
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, interleaved banks, big endian, 16-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_be_16(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 1);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 1;
|
|
|
|
if (addr & 1)
|
|
return mem_array_0[bank_nr][idx];
|
|
else
|
|
return mem_array_1[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, interleaved banks, big endian, 32-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_be_32(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 2);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 2;
|
|
|
|
switch (addr & 3)
|
|
{
|
|
case 0 : return mem_array_3[bank_nr][idx];
|
|
case 1 : return mem_array_2[bank_nr][idx];
|
|
case 2 : return mem_array_1[bank_nr][idx];
|
|
case 3 : return mem_array_0[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, interleaved banks, big endian, 64-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_be_64(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 3);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 3;
|
|
|
|
switch (addr & 7)
|
|
{
|
|
case 0 : return mem_array_7[bank_nr][idx];
|
|
case 1 : return mem_array_6[bank_nr][idx];
|
|
case 2 : return mem_array_5[bank_nr][idx];
|
|
case 3 : return mem_array_4[bank_nr][idx];
|
|
case 4 : return mem_array_3[bank_nr][idx];
|
|
case 5 : return mem_array_2[bank_nr][idx];
|
|
case 6 : return mem_array_1[bank_nr][idx];
|
|
case 7 : return mem_array_0[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, interleaved banks, little endian, 8-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_le_8(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> bit_cols;
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS));
|
|
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, interleaved banks, little endian, 16-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_le_16(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 1);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 1;
|
|
|
|
if (addr & 1)
|
|
return mem_array_1[bank_nr][idx];
|
|
else
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, interleaved banks, little endian, 32-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_le_32(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 2);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 2;
|
|
|
|
switch (addr & 3)
|
|
{
|
|
case 0 : return mem_array_0[bank_nr][idx];
|
|
case 1 : return mem_array_1[bank_nr][idx];
|
|
case 2 : return mem_array_2[bank_nr][idx];
|
|
case 3 : return mem_array_3[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, interleaved banks, little endian, 64-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_i_le_64(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + 3);
|
|
idx = (int)((addr & mask_cols) | ((addr & mask_rows) >> SDRAM_BIT_BANKS)) >> 3;
|
|
|
|
switch (addr & 7)
|
|
{
|
|
case 0 : return mem_array_0[bank_nr][idx];
|
|
case 1 : return mem_array_1[bank_nr][idx];
|
|
case 2 : return mem_array_2[bank_nr][idx];
|
|
case 3 : return mem_array_3[bank_nr][idx];
|
|
case 4 : return mem_array_4[bank_nr][idx];
|
|
case 5 : return mem_array_5[bank_nr][idx];
|
|
case 6 : return mem_array_6[bank_nr][idx];
|
|
case 7 : return mem_array_7[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, contiguous banks, big endian, 8-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_be_8(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows);
|
|
idx = (int)(addr & (mask_cols | mask_rows));
|
|
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, contiguous banks, big endian, 16-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_be_16(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 1);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 1;
|
|
|
|
if (addr & 1)
|
|
return mem_array_0[bank_nr][idx];
|
|
else
|
|
return mem_array_1[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, contiguous banks, big endian, 32-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_be_32(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 2);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 2;
|
|
|
|
switch (addr & 3)
|
|
{
|
|
case 0 : return mem_array_3[bank_nr][idx];
|
|
case 1 : return mem_array_2[bank_nr][idx];
|
|
case 2 : return mem_array_1[bank_nr][idx];
|
|
case 3 : return mem_array_0[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, contiguous banks, big endian, 64-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_be_64(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 3);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 3;
|
|
|
|
switch (addr & 7)
|
|
{
|
|
case 0 : return mem_array_7[bank_nr][idx];
|
|
case 1 : return mem_array_6[bank_nr][idx];
|
|
case 2 : return mem_array_5[bank_nr][idx];
|
|
case 3 : return mem_array_4[bank_nr][idx];
|
|
case 4 : return mem_array_3[bank_nr][idx];
|
|
case 5 : return mem_array_2[bank_nr][idx];
|
|
case 6 : return mem_array_1[bank_nr][idx];
|
|
case 7 : return mem_array_0[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, contiguous banks, little endian, 8-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_le_8(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows);
|
|
idx = (int)(addr & (mask_cols | mask_rows));
|
|
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, contiguous banks, little endian, 16-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_le_16(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 1);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 1;
|
|
|
|
if (addr & 1)
|
|
return mem_array_1[bank_nr][idx];
|
|
else
|
|
return mem_array_0[bank_nr][idx];
|
|
}
|
|
|
|
// Read a byte, contiguous banks, little endian, 32-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_le_32(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 2);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 2;
|
|
|
|
switch (addr & 3)
|
|
{
|
|
case 0 : return mem_array_0[bank_nr][idx];
|
|
case 1 : return mem_array_1[bank_nr][idx];
|
|
case 2 : return mem_array_2[bank_nr][idx];
|
|
case 3 : return mem_array_3[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Read a byte, contiguous banks, little endian, 64-bit SDRAM
|
|
vluint8_t SDRAM::read_byte_c_le_64(vluint32_t addr)
|
|
{
|
|
int bank_nr; // Bank number (0 to 3)
|
|
int idx; // Array index (0 to num_cols * num_rows - 1)
|
|
|
|
bank_nr = (int)(addr & mask_bank) >> (bit_cols + bit_rows + 3);
|
|
idx = (int)(addr & (mask_cols | mask_rows)) >> 3;
|
|
|
|
switch (addr & 7)
|
|
{
|
|
case 0 : return mem_array_0[bank_nr][idx];
|
|
case 1 : return mem_array_1[bank_nr][idx];
|
|
case 2 : return mem_array_2[bank_nr][idx];
|
|
case 3 : return mem_array_3[bank_nr][idx];
|
|
case 4 : return mem_array_4[bank_nr][idx];
|
|
case 5 : return mem_array_5[bank_nr][idx];
|
|
case 6 : return mem_array_6[bank_nr][idx];
|
|
case 7 : return mem_array_7[bank_nr][idx];
|
|
}
|
|
return 0;
|
|
}
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
// Sylvain Lefebvre 2019-09-26
|
|
|
|
#pragma once
|
|
|
|
#include "verilated.h"
|
|
|
|
class VideoOut;
|
|
|
|
/// \brief Isolates the implementation to simplify build
|
|
class VgaChip
|
|
{
|
|
private:
|
|
|
|
VideoOut *m_VideoOut = nullptr;
|
|
|
|
public:
|
|
|
|
VgaChip(int color_depth);
|
|
~VgaChip();
|
|
|
|
void eval(vluint8_t clk,
|
|
vluint8_t vs,
|
|
vluint8_t hs,
|
|
vluint8_t red,
|
|
vluint8_t green,
|
|
vluint8_t blue);
|
|
|
|
};
|
|
|
|
cmake_minimum_required(VERSION 2.6)
|
|
project(verilator_silice)
|
|
|
|
# find_package(verilator) ?
|
|
|
|
INCLUDE_DIRECTORIES(
|
|
${PROJECT_SOURCE_DIR}/
|
|
${PROJECT_SOURCE_DIR}/../../src/libs/LibSL-small/src
|
|
${PROJECT_SOURCE_DIR}/../../src/libs/LibSL-small/src/LibSL
|
|
$ENV{VERILATOR_ROOT}/include
|
|
)
|
|
|
|
add_definitions(-Wfatal-errors)
|
|
|
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
# hack to deal with https://github.com/verilator/verilator/issues/2502
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
endif()
|
|
|
|
ADD_LIBRARY(verilator_silice
|
|
video_out.cpp
|
|
video_out.h
|
|
sdr_sdram.cpp
|
|
sdr_sdram.h
|
|
VgaChip.cpp
|
|
VgaChip.h
|
|
../../src/libs/LibSL-small/src/LibSL/System/System.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/CppHelpers/CppHelpers.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/StlHelpers/StlHelpers.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/Math/Math.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/Math/Vertex.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/Image/Image.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/Image/ImageFormat_TGA.cpp
|
|
../../src/libs/LibSL-small/src/LibSL/Image/tga.cpp
|
|
)
|
|
|
|
INSTALL(TARGETS verilator_silice ARCHIVE DESTINATION ${CMAKE_SOURCE_DIR})
|
|
|
|
/*
|
|
|
|
Silice FPGA language and compiler
|
|
(c) Sylvain Lefebvre - @sylefeb
|
|
|
|
This work and all associated files are under the
|
|
|
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
|
Version 3, 19 November 2007
|
|
|
|
A copy of the license full text is included in
|
|
the distribution, please refer to it for details.
|
|
|
|
(header_1_0)
|
|
*/
|
|
//
|
|
// Implements VGA emulation for Verilator.
|
|
// Emulates front/back porch on horizontal and vertical synch.
|
|
//
|
|
// Based on code from the MCC216 project (https://github.com/fredrequin/fpga_1943)
|
|
// (c) Frederic Requin, GPL v3 license
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "verilated.h"
|
|
#include "LibSL/Image/Image.h"
|
|
|
|
#define HS_POS_POL 1
|
|
#define HS_NEG_POL 0
|
|
#define VS_POS_POL 2
|
|
#define VS_NEG_POL 0
|
|
|
|
class VideoOut
|
|
{
|
|
public:
|
|
|
|
// Constructor and destructor
|
|
VideoOut(
|
|
vluint8_t debug,
|
|
vluint8_t depth,
|
|
vluint8_t polarity,
|
|
vluint16_t hactive, vluint16_t hfporch_, vluint16_t hspulse_, vluint16_t hbporch_,
|
|
vluint16_t vactive, vluint16_t vfporch_, vluint16_t vspulse_, vluint16_t vbporch_,
|
|
const char *file);
|
|
~VideoOut();
|
|
// Methods
|
|
void eval_RGB_HV(vluint8_t clk, vluint8_t vs, vluint8_t hs, vluint8_t red, vluint8_t green, vluint8_t blue);
|
|
vluint16_t get_hcount();
|
|
vluint16_t get_vcount();
|
|
private:
|
|
// Color depth
|
|
int bit_shift;
|
|
vluint8_t bit_mask;
|
|
// Synchros polarities
|
|
vluint8_t hs_pol;
|
|
vluint8_t vs_pol;
|
|
// Debug mode
|
|
vluint8_t dbg_on;
|
|
// H synch
|
|
vluint16_t hfporch;
|
|
vluint16_t hspulse;
|
|
vluint16_t hbporch;
|
|
// V synch
|
|
vluint16_t vfporch;
|
|
vluint16_t vspulse;
|
|
vluint16_t vbporch;
|
|
// Image format
|
|
vluint16_t hor_size;
|
|
vluint16_t ver_size;
|
|
// Pixel array
|
|
LibSL::Memory::Array::Array2D<LibSL::Math::v3b> pixels;
|
|
// Image file name
|
|
std::string filename;
|
|
// Internal variable
|
|
vluint16_t hcount;
|
|
vluint16_t vcount;
|
|
vluint8_t prev_clk;
|
|
vluint8_t prev_hs;
|
|
vluint8_t prev_vs;
|
|
int dump_ctr;
|
|
|
|
enum e_Synch {e_Front=0,e_SynchPulseUp=1,e_SynchPulseDown=2,e_Back=3,e_Done=4};
|
|
|
|
e_Synch v_sync_stage;
|
|
e_Synch h_sync_stage;
|
|
int v_sync_count;
|
|
int h_sync_count;
|
|
};
|
|
|
|
{
|
|
"boards" : [
|
|
{
|
|
"name" : "icarus"
|
|
},
|
|
{
|
|
"name" : "verilator"
|
|
},
|
|
{
|
|
"name" : "icebreaker"
|
|
},
|
|
{
|
|
"name" : "icestick"
|
|
},
|
|
{
|
|
"name" : "ulx3s"
|
|
},
|
|
{
|
|
"name" : "de10nano"
|
|
},
|
|
{
|
|
"name" : "orangecrab"
|
|
},
|
|
{
|
|
"name" : "crosslink_nx_evn"
|
|
},
|
|
{
|
|
"name" : "fomu"
|
|
},
|
|
{
|
|
"name" : "mojov3"
|
|
},
|
|
{
|
|
"name" : "techgraph"
|
|
},
|
|
{
|
|
"name" : "8bitworkshop"
|
|
}
|
|
]
|
|
}
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build*
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
yosys -q -p "synth_ice40 -json build.json" build.v
|
|
nextpnr-ice40 --up5k --freq 13 --package sg48 --json build.json --pcf $BOARD_DIR/icebreaker.pcf --asc build.asc
|
|
|
|
icepack build.asc build.bin
|
|
iceprog build.bin
|
|
# ----------------------------------------------------------------------------
|
|
#
|
|
# Icebreaker constraint file (.pcf)
|
|
# Pinout:
|
|
# https://github.com/icebreaker-fpga/icebreaker/blob/master/img/icebreaker-v1_0b-legend.jpg
|
|
# Link
|
|
# https://1bitsquared.com/collections/fpga/products/icebreaker
|
|
#
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# -------------------------- SYSTEM CLOCK ------------------------------------
|
|
set_io -nowarn CLK 35
|
|
|
|
# ------------------------------ UART ----------------------------------------
|
|
set_io -nowarn RX 6
|
|
set_io -nowarn TX 9
|
|
|
|
# ------------------------- LEDs and Button ----------------------------------
|
|
set_io -nowarn BTN_N 10
|
|
set_io -nowarn LEDR_N 11
|
|
set_io -nowarn LEDG_N 37
|
|
|
|
# --------------------------- SPI Flash --------------------------------------
|
|
set_io -nowarn FLASH_SCK 15
|
|
set_io -nowarn FLASH_SSB 16
|
|
set_io -nowarn FLASH_IO0 14
|
|
set_io -nowarn FLASH_IO1 17
|
|
set_io -nowarn FLASH_IO2 12
|
|
set_io -nowarn FLASH_IO3 13
|
|
|
|
# ------------ Leds and Buttons (PMOD 2) -------------------------------------
|
|
set_io -nowarn LED1 26
|
|
set_io -nowarn LED2 27
|
|
set_io -nowarn LED3 25
|
|
set_io -nowarn LED4 23
|
|
set_io -nowarn LED5 21
|
|
set_io -nowarn BTN1 20
|
|
set_io -nowarn BTN2 19
|
|
set_io -nowarn BTN3 18
|
|
|
|
# ------------ PMOD1A connector ----------------------------------------------
|
|
set_io -nowarn P1A1 4
|
|
set_io -nowarn P1A2 2
|
|
set_io -nowarn P1A3 47
|
|
set_io -nowarn P1A4 45
|
|
set_io -nowarn P1A7 3
|
|
set_io -nowarn P1A8 48
|
|
set_io -nowarn P1A9 46
|
|
set_io -nowarn P1A10 44
|
|
|
|
# ------------ PMOD1B connector ----------------------------------------------
|
|
set_io -nowarn P1B1 43
|
|
set_io -nowarn P1B2 38
|
|
set_io -nowarn P1B3 34
|
|
set_io -nowarn P1B4 31
|
|
set_io -nowarn P1B7 42
|
|
set_io -nowarn P1B8 36
|
|
set_io -nowarn P1B9 32
|
|
set_io -nowarn P1B10 28
|
|
|
|
# ------------ Leds and Buttons (PMOD 2) -------------------------------------
|
|
set_io -nowarn P2_1 27
|
|
set_io -nowarn P2_2 25
|
|
set_io -nowarn P2_3 21
|
|
set_io -nowarn P2_4 19
|
|
set_io -nowarn P2_7 26
|
|
set_io -nowarn P2_8 23
|
|
set_io -nowarn P2_9 20
|
|
set_io -nowarn P2_10 18
|
|
{
|
|
"name": "icebreaker",
|
|
"variants": [
|
|
{
|
|
"name" : "configurable",
|
|
"framework" : "icebreaker.v",
|
|
"pins" : [
|
|
{"set" : "basic"},
|
|
{"set" : "buttons", "define" : "BUTTONS=1"},
|
|
{"set" : "uart", "define" : "UART=1"},
|
|
{"set" : "vga", "define" : "VGA=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "icestorm",
|
|
"tool_options": [
|
|
{
|
|
"nextpnr_options": ["--up5k", "--freq 13", "--package sg48", "--timing-allow-fail"],
|
|
"pnr": "next"
|
|
}
|
|
],
|
|
"bitstream" : "build.bin",
|
|
"constraints": [{"name": "icebreaker.pcf", "file_type": "PCF"}],
|
|
"program": [{"cmd" : "iceprog", "args" : "build.bin"}]
|
|
},
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "icebreaker.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint5",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"buttons": [
|
|
{
|
|
"name": "btns",
|
|
"type": "uint3",
|
|
"io": "input"
|
|
}
|
|
],
|
|
"uart": [
|
|
{
|
|
"name": "uart_tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "uart_rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define ICEBREAKER 1
|
|
`default_nettype none
|
|
$$ICEBREAKER=1
|
|
$$HARDWARE=1
|
|
$$NUM_LEDS=5
|
|
$$NUM_BTNS=3
|
|
$$VGA=1
|
|
$$color_depth=6
|
|
$$color_max =63
|
|
$$config['bram_wenable_width'] = 'data'
|
|
$$config['dualport_bram_wenable0_width'] = 'data'
|
|
$$config['dualport_bram_wenable1_width'] = 'data'
|
|
|
|
module top(
|
|
output LED1,
|
|
output LED2,
|
|
output LED3,
|
|
output LED4,
|
|
output LED5,
|
|
`ifdef BUTTONS
|
|
input BTN1,
|
|
input BTN2,
|
|
input BTN3,
|
|
`endif
|
|
`ifdef UART
|
|
output TX,
|
|
input RX,
|
|
`endif
|
|
`ifdef VGA
|
|
output P1A1, // r0
|
|
output P1A2, // r1
|
|
output P1A3, // r2
|
|
output P1A4, // r3
|
|
|
|
output P1A7, // b0
|
|
output P1A8, // b1
|
|
output P1A9, // b2
|
|
output P1A10, // b3
|
|
|
|
output P1B1, // g0
|
|
output P1B2, // g1
|
|
output P1B3, // g2
|
|
output P1B4, // g3
|
|
|
|
output P1B7, // hs
|
|
output P1B8, // vs
|
|
`endif
|
|
input CLK
|
|
);
|
|
|
|
wire [4:0] __main_leds;
|
|
|
|
// clock from design is used in case
|
|
// it relies on a PLL: in such cases
|
|
// we cannot use the clock fed into
|
|
// the PLL here
|
|
wire design_clk;
|
|
|
|
`ifdef VGA
|
|
wire __main_out_vga_hs;
|
|
wire __main_out_vga_vs;
|
|
wire __main_out_vga_v0;
|
|
wire [5:0] __main_out_vga_r;
|
|
wire [5:0] __main_out_vga_g;
|
|
wire [5:0] __main_out_vga_b;
|
|
`endif
|
|
|
|
reg ready = 0;
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge design_clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 32'b111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.clock(CLK),
|
|
.out_clock(design_clk),
|
|
.reset(RST_d[0]),
|
|
.out_leds(__main_leds),
|
|
`ifdef BUTTONS
|
|
.in_btns({BTN3,BTN2,BTN1}),
|
|
`endif
|
|
`ifdef UART
|
|
.out_uart_tx(TX),
|
|
.in_uart_rx(RX),
|
|
`endif
|
|
`ifdef VGA
|
|
.out_video_hs(__main_out_vga_hs),
|
|
.out_video_vs(__main_out_vga_vs),
|
|
.out_video_r(__main_out_vga_r),
|
|
.out_video_g(__main_out_vga_g),
|
|
.out_video_b(__main_out_vga_b),
|
|
`endif
|
|
.in_run(run_main)
|
|
);
|
|
|
|
assign LED1 = __main_leds[0+:1];
|
|
assign LED2 = __main_leds[1+:1];
|
|
assign LED3 = __main_leds[2+:1];
|
|
assign LED4 = __main_leds[3+:1];
|
|
assign LED5 = __main_leds[4+:1];
|
|
|
|
`ifdef VGA
|
|
assign P1A1 = __main_out_vga_r[2+:1];
|
|
assign P1A2 = __main_out_vga_r[3+:1];
|
|
assign P1A3 = __main_out_vga_r[4+:1];
|
|
assign P1A4 = __main_out_vga_r[5+:1];
|
|
|
|
assign P1A7 = __main_out_vga_b[2+:1];
|
|
assign P1A8 = __main_out_vga_b[3+:1];
|
|
assign P1A9 = __main_out_vga_b[4+:1];
|
|
assign P1A10 = __main_out_vga_b[5+:1];
|
|
|
|
assign P1B1 = __main_out_vga_g[2+:1];
|
|
assign P1B2 = __main_out_vga_g[3+:1];
|
|
assign P1B3 = __main_out_vga_g[4+:1];
|
|
assign P1B4 = __main_out_vga_g[5+:1];
|
|
|
|
assign P1B7 = __main_out_vga_hs;
|
|
assign P1B8 = __main_out_vga_vs;
|
|
`endif
|
|
|
|
endmodule
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build*
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
yosys -p 'synth_ecp5 -abc9 -json build.json' build.v
|
|
|
|
nextpnr-ecp5 --25k --package CSFBGA285 --json build.json --textcfg build.config --lpf $BOARD_DIR/pinout.lpf --timing-allow-fail --freq 38.8
|
|
|
|
ecppack --freq 38.8 --compress build.config build.bit
|
|
|
|
cp build.bit build.dfu
|
|
dfu-suffix -v 1209 -p 5af0 -a build.dfu
|
|
dfu-util -D build.dfu
|
|
`define ORANGECRAB 1
|
|
`default_nettype none
|
|
$$ORANGECRAB=1
|
|
$$HARDWARE=1
|
|
$$NUM_LEDS=3
|
|
|
|
module top(
|
|
input CLK, // 38.8 MHz
|
|
// bare
|
|
output [2:0] LED
|
|
);
|
|
|
|
// input/output wires
|
|
|
|
wire [2:0] __main_out_leds;
|
|
|
|
assign LED = __main_out_leds;
|
|
|
|
// reset
|
|
|
|
reg ready = 0;
|
|
|
|
reg [15:0] RST_d;
|
|
reg [15:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 16'b1111111111111111;
|
|
end
|
|
end
|
|
|
|
// main
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.clock (CLK),
|
|
.reset (RST_q[0]),
|
|
.in_run (run_main),
|
|
.out_leds (__main_out_leds)
|
|
);
|
|
|
|
endmodule
|
|
{
|
|
"name": "orangecrab",
|
|
"variants": [
|
|
{
|
|
"name" : "r2_0",
|
|
"framework" : "orangecrab.v",
|
|
"pins" : [
|
|
{"set" : "basic"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "trellis",
|
|
"tool_options": [
|
|
{
|
|
"nextpnr_options": ["--25k", "--freq 38.8", "--package CSFBGA285", "--timing-allow-fail"],
|
|
"pnr": "next"
|
|
}
|
|
],
|
|
"bitstream" : "build.dfu",
|
|
"constraints": [{"name": "pinout.lpf", "file_type": "LPF"}],
|
|
"program": [
|
|
{"cmd" : "cp", "args" : "build.bit build.dfu"},
|
|
{"cmd" : "dfu-suffix", "args" : "-v 1209 -p 5af0 -a build.dfu"},
|
|
{"cmd" : "dfu-util", "args" : "-D build.dfu"}
|
|
]
|
|
},
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "orangecrab.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "led",
|
|
"type": "uint3",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
# base on https://github.com/FPGAwars/icestudio/blob/develop/app/resources/boards/orangecrab-r02-25f/pinout.lpf
|
|
|
|
LOCATE COMP "CLK" SITE "A9"; # input
|
|
IOBUF PORT "CLK" IO_TYPE=LVCMOS33;
|
|
|
|
LOCATE COMP "LED[0]" SITE "K4"; # output
|
|
LOCATE COMP "LED[1]" SITE "M3"; # output
|
|
LOCATE COMP "LED[2]" SITE "J3"; # output
|
|
|
|
LOCATE COMP "RST" SITE "T15"; # inout
|
|
LOCATE COMP "A[0]" SITE "L4"; # inout
|
|
LOCATE COMP "A[1]" SITE "N3"; # inout
|
|
LOCATE COMP "A[2]" SITE "N4"; # inout
|
|
LOCATE COMP "A[3]" SITE "H4"; # inout
|
|
LOCATE COMP "A[4]" SITE "G4"; # inout
|
|
LOCATE COMP "A[5]" SITE "T17"; # inout
|
|
LOCATE COMP "SCK" SITE "R17"; # inout
|
|
LOCATE COMP "MOSI" SITE "N16"; # inout
|
|
LOCATE COMP "MISO" SITE "N15"; # inout
|
|
LOCATE COMP "G[0]" SITE "N17"; # inout
|
|
LOCATE COMP "G[1]" SITE "M18"; # inout
|
|
LOCATE COMP "SDA" SITE "C10"; # inout
|
|
LOCATE COMP "SCL" SITE "C9"; # inout
|
|
LOCATE COMP "G[5]" SITE "B10"; # inout
|
|
LOCATE COMP "G[6]" SITE "B9"; # inout
|
|
LOCATE COMP "G[9]" SITE "C8"; # inout
|
|
LOCATE COMP "G[10]" SITE "B8"; # inout
|
|
LOCATE COMP "G[11]" SITE "A8"; # inout
|
|
LOCATE COMP "G[12]" SITE "H2"; # inout
|
|
LOCATE COMP "G[13]" SITE "J2"; # inout
|
|
|
|
# TODO: add PROGRAMN and PULLMODEs if any
|
|
|
|
IOBUF PORT "LED[0]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "LED[1]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "LED[2]" IO_TYPE=LVCMOS33;
|
|
|
|
IOBUF PORT "RST" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[0]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[1]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[2]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[3]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[4]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "A[5]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "SCK" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "MOSI" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "MISO" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[0]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[1]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "SDA" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "SCL" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[5]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[6]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[9]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[10]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[11]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[12]" IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "G[13]" IO_TYPE=LVCMOS33;
|
|
#============================================================
|
|
# Additional settings
|
|
#============================================================
|
|
|
|
set_global_assignment -name ALLOW_ANY_ROM_SIZE_FOR_RECOGNITION ON
|
|
set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ON
|
|
|
|
#============================================================
|
|
# Clocks
|
|
#============================================================
|
|
|
|
# set_location_assignment PIN_V11 -to clk
|
|
# set_location_assignment PIN_E11 -to clk
|
|
set_location_assignment PIN_Y13 -to clk
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clk
|
|
|
|
#============================================================
|
|
# LEDs
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_W15 -to leds[0]
|
|
set_location_assignment PIN_AA24 -to leds[1]
|
|
set_location_assignment PIN_V16 -to leds[2]
|
|
set_location_assignment PIN_V15 -to leds[3]
|
|
set_location_assignment PIN_AF26 -to leds[4]
|
|
set_location_assignment PIN_AE26 -to leds[5]
|
|
set_location_assignment PIN_Y16 -to leds[6]
|
|
set_location_assignment PIN_AA23 -to leds[7]
|
|
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds*
|
|
|
|
#============================================================
|
|
# Keypad
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_AC24 -to kpadC[0]
|
|
set_location_assignment PIN_AD26 -to kpadC[1]
|
|
set_location_assignment PIN_AF28 -to kpadC[2]
|
|
set_location_assignment PIN_AF27 -to kpadC[3]
|
|
set_location_assignment PIN_Y15 -to kpadR[0]
|
|
set_location_assignment PIN_AA15 -to kpadR[1]
|
|
set_location_assignment PIN_AG28 -to kpadR[2]
|
|
set_location_assignment PIN_AE25 -to kpadR[3]
|
|
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to kpadC*
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to kpadR*
|
|
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to kpadR*
|
|
|
|
#============================================================
|
|
# Switches and Buttons
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_AH24 -to btns[0]
|
|
set_location_assignment PIN_AG25 -to btns[1]
|
|
set_location_assignment PIN_AG23 -to btns[2]
|
|
set_location_assignment PIN_AH17 -to btns[3]
|
|
set_location_assignment PIN_AH16 -to btns[4]
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to btns*
|
|
|
|
#============================================================
|
|
# VGA (I/O board compatible)
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_AE17 -to vga_r[0]
|
|
set_location_assignment PIN_AE20 -to vga_r[1]
|
|
set_location_assignment PIN_AF20 -to vga_r[2]
|
|
set_location_assignment PIN_AH18 -to vga_r[3]
|
|
set_location_assignment PIN_AH19 -to vga_r[4]
|
|
set_location_assignment PIN_AF21 -to vga_r[5]
|
|
|
|
set_location_assignment PIN_AE19 -to vga_g[0]
|
|
set_location_assignment PIN_AG15 -to vga_g[1]
|
|
set_location_assignment PIN_AF18 -to vga_g[2]
|
|
set_location_assignment PIN_AG18 -to vga_g[3]
|
|
set_location_assignment PIN_AG19 -to vga_g[4]
|
|
set_location_assignment PIN_AG20 -to vga_g[5]
|
|
|
|
set_location_assignment PIN_AG21 -to vga_b[0]
|
|
set_location_assignment PIN_AA20 -to vga_b[1]
|
|
set_location_assignment PIN_AE22 -to vga_b[2]
|
|
set_location_assignment PIN_AF22 -to vga_b[3]
|
|
set_location_assignment PIN_AH23 -to vga_b[4]
|
|
set_location_assignment PIN_AH21 -to vga_b[5]
|
|
|
|
set_location_assignment PIN_AH22 -to vga_hs
|
|
set_location_assignment PIN_AG24 -to vga_vs
|
|
|
|
set_location_assignment PIN_AH27 -to vga_en
|
|
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to vga_en
|
|
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to vga_*
|
|
set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to vga_*
|
|
|
|
#============================================================
|
|
# SDRAM
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_Y11 -to SDRAM_A[0]
|
|
set_location_assignment PIN_AA26 -to SDRAM_A[1]
|
|
set_location_assignment PIN_AA13 -to SDRAM_A[2]
|
|
set_location_assignment PIN_AA11 -to SDRAM_A[3]
|
|
set_location_assignment PIN_W11 -to SDRAM_A[4]
|
|
set_location_assignment PIN_Y19 -to SDRAM_A[5]
|
|
set_location_assignment PIN_AB23 -to SDRAM_A[6]
|
|
set_location_assignment PIN_AC23 -to SDRAM_A[7]
|
|
set_location_assignment PIN_AC22 -to SDRAM_A[8]
|
|
set_location_assignment PIN_C12 -to SDRAM_A[9]
|
|
set_location_assignment PIN_AB26 -to SDRAM_A[10]
|
|
set_location_assignment PIN_AD17 -to SDRAM_A[11]
|
|
set_location_assignment PIN_D12 -to SDRAM_A[12]
|
|
set_location_assignment PIN_Y17 -to SDRAM_BA[0]
|
|
set_location_assignment PIN_AB25 -to SDRAM_BA[1]
|
|
set_location_assignment PIN_E8 -to SDRAM_DQ[0]
|
|
set_location_assignment PIN_V12 -to SDRAM_DQ[1]
|
|
set_location_assignment PIN_D11 -to SDRAM_DQ[2]
|
|
set_location_assignment PIN_W12 -to SDRAM_DQ[3]
|
|
set_location_assignment PIN_AH13 -to SDRAM_DQ[4]
|
|
set_location_assignment PIN_D8 -to SDRAM_DQ[5]
|
|
set_location_assignment PIN_AH14 -to SDRAM_DQ[6]
|
|
set_location_assignment PIN_AF7 -to SDRAM_DQ[7]
|
|
set_location_assignment PIN_AE24 -to SDRAM_DQ[8]
|
|
set_location_assignment PIN_AD23 -to SDRAM_DQ[9]
|
|
set_location_assignment PIN_AE6 -to SDRAM_DQ[10]
|
|
set_location_assignment PIN_AE23 -to SDRAM_DQ[11]
|
|
set_location_assignment PIN_AG14 -to SDRAM_DQ[12]
|
|
set_location_assignment PIN_AD5 -to SDRAM_DQ[13]
|
|
set_location_assignment PIN_AF4 -to SDRAM_DQ[14]
|
|
set_location_assignment PIN_AH3 -to SDRAM_DQ[15]
|
|
set_location_assignment PIN_AG13 -to SDRAM_DQML
|
|
set_location_assignment PIN_AF13 -to SDRAM_DQMH
|
|
set_location_assignment PIN_AD20 -to SDRAM_CLK
|
|
set_location_assignment PIN_AG10 -to SDRAM_CKE
|
|
set_location_assignment PIN_AA19 -to SDRAM_nWE
|
|
set_location_assignment PIN_AA18 -to SDRAM_nCAS
|
|
set_location_assignment PIN_Y18 -to SDRAM_nCS
|
|
set_location_assignment PIN_W14 -to SDRAM_nRAS
|
|
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_*
|
|
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_*
|
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_*
|
|
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*]
|
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*]
|
|
set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_*
|
|
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQML
|
|
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQMH
|
|
|
|
#============================================================
|
|
# UART
|
|
#============================================================
|
|
|
|
set_location_assignment PIN_AG11 -to uart_rx
|
|
set_location_assignment PIN_AH9 -to uart_tx
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_rx
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart_tx
|
|
|
|
set_location_assignment PIN_AG8 -to uart2_rx
|
|
set_location_assignment PIN_AH8 -to uart2_tx
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart2_rx
|
|
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to uart2_tx
|
|
{
|
|
"name": "de10nano",
|
|
"variants": [
|
|
{
|
|
"name": "configurable",
|
|
"framework" : "de10nano.v",
|
|
"pins": [
|
|
{"set" : "basic"},
|
|
{"set" : "buttons","define" : "BUTTONS=1"},
|
|
{"set" : "vga", "define" : "VGA=1"},
|
|
{"set" : "sdram", "define" : "SDRAM=1"},
|
|
{"set" : "uart", "define" : "UART=1"},
|
|
{"set" : "uart2", "define" : "UART2=1"},
|
|
{"set" : "keypad", "define" : "KEYPAD=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "quartus",
|
|
"tool_options": [
|
|
{
|
|
"family": "Cyclone V",
|
|
"device": "5CSEBA6U23I7",
|
|
"cable" : "DE-SoC",
|
|
"board_device_index" : 2
|
|
}
|
|
],
|
|
"toplevel" : "top",
|
|
"bitstream" : "build.sof",
|
|
"constraints": [
|
|
{"name": "build.sdc", "file_type": "SDC"},
|
|
{"name": "pins.tcl", "file_type": "tclSource"}
|
|
],
|
|
"program": [
|
|
{"cmd" : "quartus_pgm", "args" : "-m jtag -o \"p;build.sof@2\""}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io" : "output"
|
|
}
|
|
],
|
|
"uart": [
|
|
{
|
|
"name": "uart_tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "uart_rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"uart2": [
|
|
{
|
|
"name": "tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"keypad" : [
|
|
{
|
|
"name": "kpadC",
|
|
"type": "uint4",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "kpadR",
|
|
"type": "uint4",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"buttons" : [
|
|
{
|
|
"name": "btns",
|
|
"type": "uint5",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"sdram": [
|
|
{
|
|
"name": "sdram_dq",
|
|
"type": "uint16",
|
|
"io": "inout"
|
|
},
|
|
{
|
|
"name": "sdram_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cle",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_dqm",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_we",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cas",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ras",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ba",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_a",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
# inform quartus that the clk port brings a 50MHz clock into our design so
|
|
# that timing closure on our design can be analyzed
|
|
|
|
create_clock -name clk -period "50MHz" [get_ports clk]
|
|
derive_pll_clocks -create_base_clocks
|
|
derive_clock_uncertainty
|
|
|
|
# inform quartus that the LED output port has no critical timing requirements
|
|
# its a single output port driving an LED, there are no timing relationships
|
|
# that are critical for this
|
|
|
|
set_false_path -from * -to [get_ports leds[0]]
|
|
set_false_path -from * -to [get_ports leds[1]]
|
|
set_false_path -from * -to [get_ports leds[2]]
|
|
set_false_path -from * -to [get_ports leds[3]]
|
|
set_false_path -from * -to [get_ports leds[4]]
|
|
set_false_path -from * -to [get_ports leds[5]]
|
|
set_false_path -from * -to [get_ports leds[6]]
|
|
set_false_path -from * -to [get_ports leds[7]]
|
|
`define DE10NANO 1
|
|
$$DE10NANO = 1
|
|
$$HARDWARE = 1
|
|
$$NUM_LEDS = 8
|
|
$$NUM_BTNS = 5
|
|
$$if YOSYS then
|
|
$$config['bram_wenable_width'] = 'data'
|
|
$$config['dualport_bram_wenable0_width'] = 'data'
|
|
$$config['dualport_bram_wenable1_width'] = 'data'
|
|
$$else
|
|
$$config['dualport_bram_template'] = 'dualport_bram_altera.v.in'
|
|
$$end
|
|
$$color_depth = 6
|
|
$$color_max = 63
|
|
|
|
`ifdef UART
|
|
`ifdef UART2
|
|
`error_choose_either_uart_or_uart2
|
|
`endif
|
|
`endif
|
|
|
|
module top(
|
|
output [7:0] leds,
|
|
`ifdef BUTTONS
|
|
// buttons
|
|
input [4:0] btns,
|
|
`endif
|
|
`ifdef SDRAM
|
|
// sdram
|
|
output SDRAM_CLK,
|
|
output SDRAM_CKE,
|
|
output SDRAM_DQML,
|
|
output SDRAM_DQMH,
|
|
output SDRAM_nCS,
|
|
output SDRAM_nWE,
|
|
output SDRAM_nCAS,
|
|
output SDRAM_nRAS,
|
|
output [1:0] SDRAM_BA,
|
|
output [12:0] SDRAM_A,
|
|
inout [15:0] SDRAM_DQ,
|
|
`endif
|
|
`ifdef VGA
|
|
// vga
|
|
output vga_hs,
|
|
output vga_vs,
|
|
output [5:0] vga_r,
|
|
output [5:0] vga_g,
|
|
output [5:0] vga_b,
|
|
`endif
|
|
`ifdef UART
|
|
// uart
|
|
input uart_rx,
|
|
output uart_tx,
|
|
`endif
|
|
`ifdef UART2
|
|
// uart, second choice
|
|
input uart2_rx,
|
|
output uart2_tx,
|
|
`endif
|
|
`ifdef KEYPAD
|
|
// keypad
|
|
output [3:0] kpadC,
|
|
input [3:0] kpadR,
|
|
`endif
|
|
// clock
|
|
input clk
|
|
);
|
|
|
|
wire [7:0] __main_out_leds;
|
|
|
|
`ifdef SDRAM
|
|
wire __main_out_sdram_clk;
|
|
wire __main_out_sdram_cle;
|
|
wire [1:0] __main_out_sdram_dqm;
|
|
wire __main_out_sdram_cs;
|
|
wire __main_out_sdram_we;
|
|
wire __main_out_sdram_cas;
|
|
wire __main_out_sdram_ras;
|
|
wire [1:0] __main_out_sdram_ba;
|
|
wire [12:0] __main_out_sdram_a;
|
|
`endif
|
|
|
|
`ifdef VGA
|
|
wire __main_out_vga_hs;
|
|
wire __main_out_vga_vs;
|
|
wire [5:0] __main_out_vga_r;
|
|
wire [5:0] __main_out_vga_g;
|
|
wire [5:0] __main_out_vga_b;
|
|
`endif
|
|
|
|
`ifdef UART
|
|
wire __main_out_uart_tx;
|
|
`endif
|
|
`ifdef UART2
|
|
wire __main_out_uart_tx;
|
|
`endif
|
|
|
|
`ifdef KEYPAD
|
|
wire [3:0] __main_out_kpadC;
|
|
`endif
|
|
|
|
// reset
|
|
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
reg ready = 0;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 32'b111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire reset_main;
|
|
assign reset_main = RST_q[0];
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.reset(reset_main),
|
|
.in_run(run_main),
|
|
.out_leds(__main_out_leds),
|
|
`ifdef BUTTONS
|
|
.in_btns(btns),
|
|
`endif
|
|
`ifdef SDRAM
|
|
.inout_sdram_dq(SDRAM_DQ),
|
|
.out_sdram_clk(__main_out_sdram_clk),
|
|
.out_sdram_cle(__main_out_sdram_cle),
|
|
.out_sdram_dqm(__main_out_sdram_dqm),
|
|
.out_sdram_cs(__main_out_sdram_cs),
|
|
.out_sdram_we(__main_out_sdram_we),
|
|
.out_sdram_cas(__main_out_sdram_cas),
|
|
.out_sdram_ras(__main_out_sdram_ras),
|
|
.out_sdram_ba(__main_out_sdram_ba),
|
|
.out_sdram_a(__main_out_sdram_a),
|
|
`endif
|
|
`ifdef VGA
|
|
.out_video_hs(__main_out_vga_hs),
|
|
.out_video_vs(__main_out_vga_vs),
|
|
.out_video_r(__main_out_vga_r),
|
|
.out_video_g(__main_out_vga_g),
|
|
.out_video_b(__main_out_vga_b),
|
|
`endif
|
|
`ifdef UART
|
|
.out_uart_tx(__main_out_uart_tx),
|
|
.in_uart_rx(uart_rx),
|
|
`endif
|
|
`ifdef UART2
|
|
.out_uart_tx(__main_out_uart_tx),
|
|
.in_uart_rx(uart2_rx),
|
|
`endif
|
|
`ifdef KEYPAD
|
|
.out_kpadC(__main_out_kpadC),
|
|
.in_kpadR(kpadR),
|
|
`endif
|
|
.clock(clk)
|
|
);
|
|
|
|
assign leds = __main_out_leds;
|
|
|
|
`ifdef SDRAM
|
|
assign SDRAM_CLK = __main_out_sdram_clk;
|
|
assign SDRAM_CKE = __main_out_sdram_cle;
|
|
assign SDRAM_DQML = __main_out_sdram_dqm[0];
|
|
assign SDRAM_DQMH = __main_out_sdram_dqm[1];
|
|
assign SDRAM_nCS = __main_out_sdram_cs;
|
|
assign SDRAM_nWE = __main_out_sdram_we;
|
|
assign SDRAM_nCAS = __main_out_sdram_cas;
|
|
assign SDRAM_nRAS = __main_out_sdram_ras;
|
|
assign SDRAM_BA = __main_out_sdram_ba;
|
|
assign SDRAM_A = __main_out_sdram_a;
|
|
`endif
|
|
|
|
`ifdef VGA
|
|
assign vga_hs = __main_out_vga_hs;
|
|
assign vga_vs = __main_out_vga_vs;
|
|
assign vga_r = __main_out_vga_r;
|
|
assign vga_g = __main_out_vga_g;
|
|
assign vga_b = __main_out_vga_b;
|
|
`endif
|
|
|
|
`ifdef UART
|
|
assign uart_tx = __main_out_uart_tx;
|
|
`endif
|
|
`ifdef UART2
|
|
assign uart2_tx = __main_out_uart_tx;
|
|
`endif
|
|
|
|
`ifdef KEYPAD
|
|
assign kpadC = __main_out_kpadC;
|
|
`endif
|
|
|
|
endmodule
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR:"/c/Program Files (x86)/Graphviz2.38/bin/"
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build.v
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
yosys -p 'synth_ice40 ; show -width -stretch -colors 4242' build.v
|
|
|
|
dot -Tpdf:cairo show.dot -O
|
|
`define YOSYS 1
|
|
`default_nettype none
|
|
$$HARDWARE = 1
|
|
$$NUM_LEDS = 4
|
|
|
|
module top(
|
|
// LED outputs
|
|
output [3:0] leds,
|
|
input clk
|
|
);
|
|
|
|
wire [7:0] __main_leds;
|
|
|
|
reg reset = 1;
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
reset <= 0;
|
|
end
|
|
end
|
|
|
|
M_main __main(
|
|
.clock (clk),
|
|
.reset (reset),
|
|
.out_leds (__main_leds),
|
|
.in_run (~reset)
|
|
);
|
|
|
|
assign leds = __main_leds;
|
|
|
|
endmodule
|
|
{
|
|
"name": "techgraph",
|
|
"variants": [
|
|
{
|
|
"name" : "techgraph",
|
|
"framework" : "techgraph.v",
|
|
"pins" : [
|
|
{"set" : "basic"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "techgraph.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define VERILATOR 1
|
|
`define COLOR_DEPTH 1
|
|
|
|
/*verilator lint_off pinmissing */
|
|
/*verilator lint_off undriven */
|
|
|
|
$$VERILATOR = 1
|
|
$$NUM_LEDS = 0
|
|
$$SIMULATION = 1
|
|
$$color_depth = 1
|
|
$$color_max = 1
|
|
|
|
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
module top(
|
|
// NTSC
|
|
output reg [`COLOR_DEPTH*3-1:0] rgb,
|
|
output hsync,
|
|
output vsync,
|
|
input clk,
|
|
input reset
|
|
);
|
|
|
|
wire [`COLOR_DEPTH-1:0] __main_video_r;
|
|
wire [`COLOR_DEPTH-1:0] __main_video_g;
|
|
wire [`COLOR_DEPTH-1:0] __main_video_b;
|
|
wire __main_video_hs;
|
|
wire __main_video_vs;
|
|
|
|
// main
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
wire done_main;
|
|
|
|
M_main __main(
|
|
.clock(clk),
|
|
.reset(reset),
|
|
`ifdef NTSC
|
|
.out_video_r(__main_video_r),
|
|
.out_video_g(__main_video_g),
|
|
.out_video_b(__main_video_b),
|
|
.out_video_hs(__main_video_hs),
|
|
.out_video_vs(__main_video_vs),
|
|
`endif
|
|
.in_run(run_main),
|
|
.out_done(done_main)
|
|
);
|
|
|
|
assign rgb = {__main_video_b[0], __main_video_g[0], __main_video_r[0]};
|
|
assign hsync = __main_video_hs;
|
|
assign vsync = __main_video_vs;
|
|
|
|
endmodule
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
if hash make 2>/dev/null; then
|
|
export MAKE=make
|
|
else
|
|
export MAKE=mingw32-make
|
|
fi
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
|
|
if [[ -z "${VERILATOR_ROOT}" ]]; then
|
|
case "$(uname -s)" in
|
|
Linux)
|
|
unset VERILATOR_ROOT
|
|
;;
|
|
*)
|
|
export VERILATOR_ROOT=$SILICE_DIR/../tools/fpga-binutils/mingw64/
|
|
;;
|
|
esac
|
|
echo "VERILATOR_ROOT is set to ${VERILATOR_ROOT}"
|
|
else
|
|
echo "VERILATOR_ROOT already defined, using its value"
|
|
fi
|
|
|
|
u=$(echo "$1" | sed s:/:__:g | tr -d ".")
|
|
|
|
echo "using directory $u"
|
|
|
|
cd $BUILD_DIR
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
if [[ -z "${VGA}" ]] && [[ -z "${SDRAM}" ]]; then
|
|
VERILATOR_LIB="verilator_bare"
|
|
else
|
|
VERILATOR_LIB="verilator_vga"
|
|
fi
|
|
|
|
#echo "using verilator framework $VERILATOR_LIB"
|
|
|
|
#verilator -Wno-PINMISSING -Wno-WIDTH -O3 -cc build.v --top-module top
|
|
#cd obj_dir
|
|
#$MAKE -f Vtop.mk
|
|
#$MAKE -f Vtop.mk $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o
|
|
#g++ -O3 $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o Vtop__ALL.a $SILICE_DIR/../frameworks/verilator/libverilator_silice.a -o ../run_simul
|
|
#cd ..
|
|
|
|
#./run_simul
|
|
{
|
|
"name": "8bitworkshop",
|
|
"variants": [
|
|
{
|
|
"name" : "configurable",
|
|
"framework" : "8bitworkshop.v",
|
|
"pins" : [
|
|
{"set" : "ntsc", "define" : "NTSC=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "8bitworkshop.sh",
|
|
"description": "Simulates with 8bitworkshop"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"ntsc": [
|
|
{
|
|
"name": "hsync",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vsync",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "rgb",
|
|
"type": "uint3",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"paddles": [
|
|
{
|
|
"name": "hpaddle",
|
|
"type": "uint1",
|
|
"io": "input"
|
|
},
|
|
{
|
|
"name": "vpaddle",
|
|
"type": "uint1",
|
|
"io": "input"
|
|
}
|
|
],
|
|
"switches": [
|
|
{
|
|
"name": "switches_p1",
|
|
"type": "uint8",
|
|
"io": "input"
|
|
},
|
|
{
|
|
"name": "switches_p2",
|
|
"type": "uint8",
|
|
"io": "input"
|
|
}
|
|
],
|
|
"keyboard": [
|
|
{
|
|
"name": "keycode",
|
|
"type": "uint8",
|
|
"io": "input"
|
|
},
|
|
{
|
|
"name": "keystrobe",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
{
|
|
"name": "fomu",
|
|
"variants": [
|
|
{
|
|
"name" : "hacker",
|
|
"framework" : "fomu.v",
|
|
"pins" : [
|
|
{"set" : "basic"},
|
|
{"set" : "usb", "define" : "USB=1"},
|
|
{"set" : "spi", "define" : "SPI=1"},
|
|
{"set" : "pads", "define" : "PADS=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "fomu.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint3",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"usb": [
|
|
{
|
|
"name": "usb_dp",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "usb_dn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "usb_dp_pu",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"spi": [
|
|
{
|
|
"name": "spi_mosi",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "spi_miso",
|
|
"type": "uint1",
|
|
"io": "input"
|
|
},
|
|
{
|
|
"name": "spi_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "spi_cs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"pads": [
|
|
{
|
|
"name": "user_pads",
|
|
"type": "uint4",
|
|
"io": "input"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
# Configuration for the Fomu hacker board.
|
|
set_io rgb0 A5 # Blue LED
|
|
set_io rgb1 B5 # Green LED
|
|
set_io rgb2 C5 # Red LED
|
|
set_io clki F5 # Clock input from 48MHz Oscillator
|
|
set_io spi_mosi F1 # SPI Master Out, Slave In Pin
|
|
set_io spi_miso E1 # SPI Master In, Slave Out Pin
|
|
set_io spi_clk D1 # SPI Master Clock Output Pin
|
|
set_io spi_cs C1 # SPI Chip Select
|
|
set_io user_1 F4 # User touch pad 1
|
|
set_io user_2 E5 # User touch pad 2
|
|
set_io user_3 E4 # User touch pad 3
|
|
set_io user_4 F2 # User touch pad 4
|
|
set_io usb_dn A2 # USB D- pad
|
|
set_io usb_dp A4 # USB D+ pad
|
|
set_io usb_dp_pu D5 # USB D+ pull up (indicates device connected)
|
|
// credits: rob-ng15 - see also https://github.com/rob-ng15/Silice-Playground/
|
|
`define FOMU 1
|
|
`default_nettype none
|
|
$$FOMU = 1
|
|
$$HARDWARE = 1
|
|
$$NUM_LEDS = 3
|
|
|
|
// Correctly map pins for the iCE40UP5K SB_RGBA_DRV hard macro.
|
|
// The variables EVT, PVT and HACKER are set from the yosys commandline e.g. yosys -D HACKER=1
|
|
`ifdef EVT
|
|
`define BLUEPWM RGB0PWM
|
|
`define REDPWM RGB1PWM
|
|
`define GREENPWM RGB2PWM
|
|
`elsif HACKER
|
|
`define BLUEPWM RGB0PWM
|
|
`define GREENPWM RGB1PWM
|
|
`define REDPWM RGB2PWM
|
|
`elsif PVT
|
|
`define GREENPWM RGB0PWM
|
|
`define REDPWM RGB1PWM
|
|
`define BLUEPWM RGB2PWM
|
|
`else
|
|
`error_board_not_supported
|
|
`endif
|
|
|
|
module top(
|
|
// LED outputs
|
|
output rgb0,
|
|
output rgb1,
|
|
output rgb2,
|
|
// USB Pins
|
|
output usb_dp,
|
|
output usb_dn,
|
|
output usb_dp_pu,
|
|
`ifdef SPI
|
|
// SPI
|
|
output spi_mosi,
|
|
input spi_miso,
|
|
output spi_clk,
|
|
output spi_cs,
|
|
`endif
|
|
`ifdef PADS
|
|
// USER pads
|
|
input [3:0] user_pads,
|
|
`endif
|
|
// 48MHz Clock Input
|
|
input clki
|
|
);
|
|
|
|
`ifdef USB
|
|
wire __main_usb_dp;
|
|
wire __main_usb_dn;
|
|
wire __main_usb_dp_pu;
|
|
assign usb_dp = __main_usb_dp;
|
|
assign usb_dn = __main_usb_dn;
|
|
assign usb_dp_pu = __main_usb_dp_pu;
|
|
`else
|
|
// Assign USB pins to "0" so as to disconnect Fomu from
|
|
// the host system. Otherwise it would try to talk to
|
|
// us over USB, which wouldn't work since we have no stack.
|
|
assign usb_dp = 1'b0;
|
|
assign usb_dn = 1'b0;
|
|
assign usb_dp_pu = 1'b0;
|
|
`endif
|
|
|
|
`ifdef SPI
|
|
wire __main_spi_mosi;
|
|
wire __main_spi_clk;
|
|
wire __main_spi_cs;
|
|
assign spi_mosi = __main_spi_mosi;
|
|
assign spi_clk = __main_spi_clk;
|
|
assign spi_cs = __main_spi_cs;
|
|
`endif
|
|
|
|
// Connect to system clock (with buffering)
|
|
wire clk;
|
|
SB_GB clk_gb (
|
|
.USER_SIGNAL_TO_GLOBAL_BUFFER(clki),
|
|
.GLOBAL_BUFFER_OUTPUT(clk)
|
|
);
|
|
|
|
wire [2:0] __main_leds;
|
|
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
reg ready = 0;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 32'b111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire reset_main;
|
|
assign reset_main = RST_q[0];
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.clock (clk),
|
|
.reset (RST_q[0]),
|
|
.out_leds (__main_leds),
|
|
`ifdef USB
|
|
.out_usb_dp (__main_usb_dp),
|
|
.out_usb_dn (__main_usb_dn),
|
|
.out_usb_dp_pu(__main_usb_dp_pu),
|
|
`endif
|
|
`ifdef SPI
|
|
.out_spi_mosi (__main_spi_mosi),
|
|
.in_spi_miso (spi_miso),
|
|
.out_spi_clk (__main_spi_clk),
|
|
.out_spi_cs (__main_spi_cs),
|
|
`endif
|
|
`ifdef PADS
|
|
.in_user_pads(user_pads),
|
|
`endif
|
|
.in_run (run_main)
|
|
);
|
|
|
|
SB_RGBA_DRV #(
|
|
.CURRENT_MODE("0b1"), // half current
|
|
.RGB0_CURRENT("0b000011"), // 4 mA
|
|
.RGB1_CURRENT("0b000011"), // 4 mA
|
|
.RGB2_CURRENT("0b000011") // 4 mA
|
|
) RGBA_DRIVER (
|
|
.CURREN(1'b1),
|
|
.RGBLEDEN(1'b1),
|
|
.`BLUEPWM (__main_leds[0]), // Blue
|
|
.`REDPWM (__main_leds[1]), // Red
|
|
.`GREENPWM(__main_leds[2]), // Green
|
|
.RGB0(rgb0),
|
|
.RGB1(rgb1),
|
|
.RGB2(rgb2)
|
|
);
|
|
|
|
endmodule
|
|
#!/bin/bash
|
|
|
|
# credits: rob-ng15 -- see also https://github.com/rob-ng15/Silice-Playground
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build*
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
yosys -D HACKER=1 -p 'synth_ice40 -top top -json build.json' build.v
|
|
|
|
nextpnr-ice40 --up5k --package uwg30 --opt-timing --pcf $BOARD_DIR/fomu-hacker.pcf --json build.json --asc build.asc
|
|
|
|
icepack build.asc build.bit
|
|
icetime -d up5k -mtr build.rpt build.asc
|
|
|
|
cp build.bit build.dfu
|
|
dfu-suffix -v 1209 -p 70b1 -a build.dfu
|
|
dfu-util -D build.dfu
|
|
`define ULX3S 1
|
|
`default_nettype none
|
|
$$ULX3S = 1
|
|
$$HARDWARE = 1
|
|
$$NUM_LEDS = 8
|
|
$$NUM_BTNS = 7
|
|
$$color_depth = 6
|
|
$$color_max = 63
|
|
$$config['dualport_bram_supported'] = 'no'
|
|
|
|
module top(
|
|
// basic
|
|
output [7:0] leds,
|
|
// buttons
|
|
input [6:0] btns,
|
|
`ifdef SDRAM
|
|
// sdram
|
|
output sdram_clk,
|
|
output sdram_cke,
|
|
output [1:0] sdram_dqm,
|
|
output sdram_csn,
|
|
output sdram_wen,
|
|
output sdram_casn,
|
|
output sdram_rasn,
|
|
output [1:0] sdram_ba,
|
|
output [12:0] sdram_a,
|
|
inout [15:0] sdram_d,
|
|
`endif
|
|
`ifdef AUDIO
|
|
output [3:0] audio_l,
|
|
output [3:0] audio_r,
|
|
`endif
|
|
`ifdef OLED
|
|
// oled
|
|
output oled_clk,
|
|
output oled_mosi,
|
|
output oled_dc,
|
|
output oled_resn,
|
|
output oled_csn,
|
|
`endif
|
|
`ifdef SDCARD
|
|
// sdcard
|
|
output sd_clk,
|
|
output sd_csn,
|
|
output sd_mosi,
|
|
input sd_miso,
|
|
`endif
|
|
`ifdef GPIO
|
|
// gpio
|
|
output [27:0] gp,
|
|
input [27:0] gn,
|
|
`endif
|
|
`ifdef VGA
|
|
// vga
|
|
output [27:0] gp,
|
|
input [27:0] gn,
|
|
`endif
|
|
`ifdef HDMI
|
|
// hdmi
|
|
output [3:0] gpdi_dp, // {clock,R,G,B}
|
|
output [3:0] gpdi_dn,
|
|
`endif
|
|
`ifdef UART
|
|
// uart
|
|
output ftdi_rxd,
|
|
input ftdi_txd,
|
|
`endif
|
|
`ifdef UART2
|
|
// uart2
|
|
`endif
|
|
input clk_25mhz
|
|
);
|
|
|
|
wire [7:0] __main_out_leds;
|
|
|
|
`ifdef OLED
|
|
wire __main_oled_clk;
|
|
wire __main_oled_mosi;
|
|
wire __main_oled_dc;
|
|
wire __main_oled_resn;
|
|
wire __main_oled_csn;
|
|
`endif
|
|
|
|
`ifdef SDRAM
|
|
wire __main_out_sdram_clk;
|
|
wire __main_out_sdram_cle;
|
|
wire [1:0] __main_out_sdram_dqm;
|
|
wire __main_out_sdram_cs;
|
|
wire __main_out_sdram_we;
|
|
wire __main_out_sdram_cas;
|
|
wire __main_out_sdram_ras;
|
|
wire [1:0] __main_out_sdram_ba;
|
|
wire [12:0] __main_out_sdram_a;
|
|
`endif
|
|
|
|
`ifdef UART2
|
|
`ifndef GPIO
|
|
`error_UART2_needs_GPIO
|
|
`endif
|
|
`endif
|
|
|
|
`ifdef UART
|
|
wire __main_out_uart_tx;
|
|
`endif
|
|
|
|
`ifdef VGA
|
|
wire __main_out_vga_hs;
|
|
wire __main_out_vga_vs;
|
|
wire [5:0] __main_out_vga_r;
|
|
wire [5:0] __main_out_vga_g;
|
|
wire [5:0] __main_out_vga_b;
|
|
`endif
|
|
|
|
`ifdef SDCARD
|
|
wire __main_sd_clk;
|
|
wire __main_sd_csn;
|
|
wire __main_sd_mosi;
|
|
`endif
|
|
|
|
`ifdef HDMI
|
|
wire [3:0] __main_out_gpdi_dp;
|
|
wire [3:0] __main_out_gpdi_dn;
|
|
`endif
|
|
|
|
`ifdef AUDIO
|
|
wire [3:0] __main_out_audio_l;
|
|
wire [3:0] __main_out_audio_r;
|
|
`endif
|
|
|
|
wire ready = btns[0];
|
|
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge clk_25mhz) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
RST_q <= 32'b111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.reset (RST_q[0]),
|
|
.in_run (run_main),
|
|
.out_leds (__main_out_leds),
|
|
`ifdef BUTTONS
|
|
.in_btns (btns),
|
|
`endif
|
|
`ifdef SDRAM
|
|
.inout_sdram_dq(sdram_d),
|
|
.out_sdram_clk (__main_out_sdram_clk),
|
|
.out_sdram_cle (__main_out_sdram_cle),
|
|
.out_sdram_dqm (__main_out_sdram_dqm),
|
|
.out_sdram_cs (__main_out_sdram_cs),
|
|
.out_sdram_we (__main_out_sdram_we),
|
|
.out_sdram_cas (__main_out_sdram_cas),
|
|
.out_sdram_ras (__main_out_sdram_ras),
|
|
.out_sdram_ba (__main_out_sdram_ba),
|
|
.out_sdram_a (__main_out_sdram_a),
|
|
`endif
|
|
`ifdef SDCARD
|
|
.out_sd_csn (__main_sd_csn),
|
|
.out_sd_clk (__main_sd_clk),
|
|
.out_sd_mosi (__main_sd_mosi),
|
|
.in_sd_miso (sd_miso),
|
|
`endif
|
|
`ifdef AUDIO
|
|
.out_audio_l (__main_out_audio_l),
|
|
.out_audio_r (__main_out_audio_r),
|
|
`endif
|
|
`ifdef OLED
|
|
.out_oled_clk (__main_oled_clk),
|
|
.out_oled_mosi(__main_oled_mosi),
|
|
.out_oled_dc (__main_oled_dc),
|
|
.out_oled_resn(__main_oled_resn),
|
|
.out_oled_csn (__main_oled_csn),
|
|
`endif
|
|
`ifdef GPIO
|
|
`ifdef UART2
|
|
.out_gp (gp[27:1]),
|
|
.in_gn (gn[27:1]),
|
|
.out_uart2_tx (gp[0]),
|
|
.in_uart2_rx (gn[0]),
|
|
`else
|
|
.out_gp (gp),
|
|
.in_gn (gn),
|
|
`endif
|
|
`endif
|
|
`ifdef UART
|
|
.out_uart_tx (__main_out_uart_tx),
|
|
.in_uart_rx (ftdi_txd),
|
|
`endif
|
|
`ifdef VGA
|
|
.out_video_hs (__main_out_vga_hs),
|
|
.out_video_vs (__main_out_vga_vs),
|
|
.out_video_r (__main_out_vga_r),
|
|
.out_video_g (__main_out_vga_g),
|
|
.out_video_b (__main_out_vga_b),
|
|
`endif
|
|
`ifdef HDMI
|
|
.out_gpdi_dp (__main_out_gpdi_dp),
|
|
.out_gpdi_dn (__main_out_gpdi_dn),
|
|
`endif
|
|
.clock (clk_25mhz)
|
|
);
|
|
|
|
assign leds = __main_out_leds;
|
|
|
|
`ifdef SDRAM
|
|
assign sdram_clk = __main_out_sdram_clk;
|
|
assign sdram_cke = __main_out_sdram_cle;
|
|
assign sdram_dqm = __main_out_sdram_dqm;
|
|
assign sdram_csn = __main_out_sdram_cs;
|
|
assign sdram_wen = __main_out_sdram_we;
|
|
assign sdram_casn = __main_out_sdram_cas;
|
|
assign sdram_rasn = __main_out_sdram_ras;
|
|
assign sdram_ba = __main_out_sdram_ba;
|
|
assign sdram_a = __main_out_sdram_a;
|
|
`endif
|
|
|
|
`ifdef AUDIO
|
|
assign audio_l = __main_out_audio_l;
|
|
assign audio_r = __main_out_audio_r;
|
|
`endif
|
|
|
|
`ifdef VGA
|
|
assign gp[0] = __main_out_vga_vs;
|
|
assign gp[1] = __main_out_vga_hs;
|
|
assign gp[2] = __main_out_vga_r[5];
|
|
assign gp[3] = __main_out_vga_r[4];
|
|
assign gp[4] = __main_out_vga_r[3];
|
|
assign gp[5] = __main_out_vga_r[2];
|
|
assign gp[6] = __main_out_vga_r[1];
|
|
assign gp[7] = __main_out_vga_r[0];
|
|
assign gp[8] = __main_out_vga_g[5];
|
|
assign gp[9] = __main_out_vga_g[4];
|
|
assign gp[10] = __main_out_vga_g[3];
|
|
assign gp[11] = __main_out_vga_g[2];
|
|
assign gp[12] = __main_out_vga_g[1];
|
|
assign gp[13] = __main_out_vga_g[0];
|
|
assign gp[14] = __main_out_vga_b[0];
|
|
assign gp[15] = __main_out_vga_b[1];
|
|
assign gp[16] = __main_out_vga_b[2];
|
|
assign gp[17] = __main_out_vga_b[3];
|
|
assign gp[18] = __main_out_vga_b[4];
|
|
assign gp[19] = __main_out_vga_b[5];
|
|
`endif
|
|
|
|
`ifdef SDCARD
|
|
assign sd_clk = __main_sd_clk;
|
|
assign sd_csn = __main_sd_csn;
|
|
assign sd_mosi = __main_sd_mosi;
|
|
`endif
|
|
|
|
`ifdef OLED
|
|
assign oled_clk = __main_oled_clk;
|
|
assign oled_mosi = __main_oled_mosi;
|
|
assign oled_dc = __main_oled_dc;
|
|
assign oled_resn = __main_oled_resn;
|
|
assign oled_csn = __main_oled_csn;
|
|
`endif
|
|
|
|
`ifdef UART
|
|
assign ftdi_rxd = __main_out_uart_tx;
|
|
`endif
|
|
|
|
`ifdef HDMI
|
|
assign gpdi_dp = __main_out_gpdi_dp;
|
|
assign gpdi_dn = __main_out_gpdi_dn;
|
|
`endif
|
|
|
|
endmodule
|
|
# https://github.com/emard/ulx3s/blob/master/doc/constraints/ulx3s_v20.lpf
|
|
|
|
BLOCK RESETPATHS;
|
|
BLOCK ASYNCPATHS;
|
|
## ULX3S v2.x.x and v3.0.x
|
|
|
|
# The clock "usb" and "gpdi" sheet
|
|
LOCATE COMP "clk_25mhz" SITE "G2";
|
|
IOBUF PORT "clk_25mhz" PULLMODE=NONE IO_TYPE=LVCMOS33;
|
|
FREQUENCY PORT "clk_25mhz" 25 MHZ;
|
|
|
|
# JTAG and SPI FLASH voltage 3.3V and options to boot from SPI flash
|
|
# write to FLASH possible any time from JTAG:
|
|
#SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=ENABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE;
|
|
# write to FLASH possible from user bitstream:
|
|
SYSCONFIG CONFIG_IOVOLTAGE=3.3 COMPRESS_CONFIG=ON MCCLK_FREQ=62 MASTER_SPI_PORT=DISABLE SLAVE_SPI_PORT=DISABLE SLAVE_PARALLEL_PORT=DISABLE;
|
|
|
|
## USBSERIAL FTDI-FPGA serial port "usb" sheet
|
|
LOCATE COMP "ftdi_rxd" SITE "L4"; # FPGA transmits to ftdi
|
|
LOCATE COMP "ftdi_txd" SITE "M1"; # FPGA receives from ftdi
|
|
LOCATE COMP "ftdi_nrts" SITE "M3"; # FPGA receives
|
|
LOCATE COMP "ftdi_ndtr" SITE "N1"; # FPGA receives
|
|
LOCATE COMP "ftdi_txden" SITE "L3"; # FPGA receives
|
|
IOBUF PORT "ftdi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "ftdi_txd" PULLMODE=UP IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "ftdi_nrts" PULLMODE=UP IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "ftdi_ndtr" PULLMODE=UP IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "ftdi_txden" PULLMODE=UP IO_TYPE=LVCMOS33;
|
|
|
|
## LED indicators "blinkey" and "gpio" sheet
|
|
LOCATE COMP "leds[7]" SITE "H3";
|
|
LOCATE COMP "leds[6]" SITE "E1";
|
|
LOCATE COMP "leds[5]" SITE "E2";
|
|
LOCATE COMP "leds[4]" SITE "D1";
|
|
LOCATE COMP "leds[3]" SITE "D2";
|
|
LOCATE COMP "leds[2]" SITE "C1";
|
|
LOCATE COMP "leds[1]" SITE "C2";
|
|
LOCATE COMP "leds[0]" SITE "B2";
|
|
IOBUF PORT "leds[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "leds[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## Pushbuttons "blinkey", "flash", "power", "gpdi" sheet
|
|
LOCATE COMP "btns[0]" SITE "D6"; # BTN_PWRn (inverted logic)
|
|
LOCATE COMP "btns[1]" SITE "R1"; # FIRE1
|
|
LOCATE COMP "btns[2]" SITE "T1"; # FIRE2
|
|
LOCATE COMP "btns[3]" SITE "R18"; # UP
|
|
LOCATE COMP "btns[4]" SITE "V1"; # DOWN
|
|
LOCATE COMP "btns[5]" SITE "U1"; # LEFT
|
|
LOCATE COMP "btns[6]" SITE "H16"; # RIGHT
|
|
IOBUF PORT "btns[0]" PULLMODE=UP IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[4]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[5]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "btns[6]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
|
|
## DIP switch "blinkey", "gpio" sheet
|
|
LOCATE COMP "sw[0]" SITE "E8"; # SW1
|
|
LOCATE COMP "sw[1]" SITE "D8"; # SW2
|
|
LOCATE COMP "sw[2]" SITE "D7"; # SW3
|
|
LOCATE COMP "sw[3]" SITE "E7"; # SW4
|
|
IOBUF PORT "sw[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "sw[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "sw[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
IOBUF PORT "sw[3]" PULLMODE=DOWN IO_TYPE=LVCMOS33;
|
|
|
|
## SPI OLED DISPLAY SSD1331 (Color) or SSD1306 (B/W) "blinkey", "usb" sheet
|
|
LOCATE COMP "oled_clk" SITE "P4";
|
|
LOCATE COMP "oled_mosi" SITE "P3";
|
|
LOCATE COMP "oled_dc" SITE "P1";
|
|
LOCATE COMP "oled_resn" SITE "P2";
|
|
LOCATE COMP "oled_csn" SITE "N2";
|
|
IOBUF PORT "oled_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "oled_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "oled_dc" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "oled_resn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "oled_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## SPI Flash chip "flash" sheet
|
|
LOCATE COMP "flash_csn" SITE "R2";
|
|
#LOCATE COMP "flash_clk" SITE "U3";
|
|
LOCATE COMP "flash_mosi" SITE "W2";
|
|
LOCATE COMP "flash_miso" SITE "V2";
|
|
LOCATE COMP "flash_holdn" SITE "W1";
|
|
LOCATE COMP "flash_wpn" SITE "Y2";
|
|
#LOCATE COMP "flash_csspin" SITE "AJ3";
|
|
#LOCATE COMP "flash_initn" SITE "AG4";
|
|
#LOCATE COMP "flash_done" SITE "AJ4";
|
|
#LOCATE COMP "flash_programn" SITE "AH4";
|
|
#LOCATE COMP "flash_cfg_select[0]" SITE "AM4";
|
|
#LOCATE COMP "flash_cfg_select[1]" SITE "AL4";
|
|
#LOCATE COMP "flash_cfg_select[2]" SITE "AK4";
|
|
IOBUF PORT "flash_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "flash_mosi" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "flash_miso" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "flash_holdn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "flash_wpn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_csspin" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_initn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_cfg_select[0]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_cfg_select[1]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "flash_cfg_select[2]" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## SD card "sdcard", "usb" sheet
|
|
LOCATE COMP "sd_clk" SITE "H2"; # sd_clk WiFi_GPIO14
|
|
LOCATE COMP "sd_mosi" SITE "J1"; # sd_cmd_di (MOSI) WiFi GPIO15
|
|
LOCATE COMP "sd_miso" SITE "J3"; # sd_dat0_do (MISO) WiFi GPIO2
|
|
LOCATE COMP "sd_csn" SITE "K2"; # sd_dat3_csn WiFi_GPIO13
|
|
IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sd_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sd_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sd_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## ADC SPI (MAX11123) "analog", "ram" sheet
|
|
LOCATE COMP "adc_csn" SITE "R17";
|
|
LOCATE COMP "adc_mosi" SITE "R16";
|
|
LOCATE COMP "adc_miso" SITE "U16";
|
|
LOCATE COMP "adc_sclk" SITE "P17";
|
|
IOBUF PORT "adc_csn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "adc_mosi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "adc_miso" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "adc_sclk" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## Audio 4-bit DAC "analog", "gpio" sheet
|
|
# Output impedance 75 ohm.
|
|
# Strong enough to drive 16 ohm earphones.
|
|
LOCATE COMP "audio_l[3]" SITE "B3"; # JACK TIP (left audio)
|
|
LOCATE COMP "audio_l[2]" SITE "C3";
|
|
LOCATE COMP "audio_l[1]" SITE "D3";
|
|
LOCATE COMP "audio_l[0]" SITE "E4";
|
|
LOCATE COMP "audio_r[3]" SITE "C5"; # JACK RING1 (right audio)
|
|
LOCATE COMP "audio_r[2]" SITE "D5";
|
|
LOCATE COMP "audio_r[1]" SITE "B5";
|
|
LOCATE COMP "audio_r[0]" SITE "A3";
|
|
LOCATE COMP "audio_v[3]" SITE "E5"; # JACK RING2 (video or digital audio)
|
|
LOCATE COMP "audio_v[2]" SITE "F5";
|
|
LOCATE COMP "audio_v[1]" SITE "F2";
|
|
LOCATE COMP "audio_v[0]" SITE "H5";
|
|
IOBUF PORT "audio_l[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_l[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_l[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_l[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_r[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_r[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_r[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_r[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_v[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_v[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_v[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "audio_v[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
|
|
## WiFi ESP-32 "wifi", "usb", "flash" sheet
|
|
# other pins are shared with GP/GN, SD card and JTAG
|
|
LOCATE COMP "wifi_en" SITE "F1"; # enable/reset WiFi
|
|
LOCATE COMP "wifi_rxd" SITE "K3"; # FPGA transmits to WiFi
|
|
LOCATE COMP "wifi_txd" SITE "K4"; # FPGA receives from WiFi
|
|
LOCATE COMP "wifi_gpio0" SITE "L2";
|
|
LOCATE COMP "wifi_gpio5" SITE "N4"; # WIFI LED
|
|
LOCATE COMP "wifi_gpio16" SITE "L1"; # Serial1 RX
|
|
LOCATE COMP "wifi_gpio17" SITE "N3"; # Serial1 TX
|
|
# LOCATE COMP "prog_done" SITE "Y3"; # not GPIO, always active
|
|
IOBUF PORT "wifi_en" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_rxd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_txd" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_gpio0" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_gpio5" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_gpio16" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "wifi_gpio17" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
# IOBUF PORT "prog_done" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## PCB antenna 433 MHz (may be also used for FM) "usb" sheet
|
|
LOCATE COMP "ant_433mhz" SITE "G1";
|
|
IOBUF PORT "ant_433mhz" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## Second USB port "US2" going directly into FPGA "usb", "ram" sheet
|
|
LOCATE COMP "usb_fpga_dp" SITE "E16"; # single ended or differential input only
|
|
LOCATE COMP "usb_fpga_dn" SITE "F16";
|
|
IOBUF PORT "usb_fpga_dp" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16;
|
|
IOBUF PORT "usb_fpga_dn" PULLMODE=NONE IO_TYPE=LVCMOS33D DRIVE=16;
|
|
LOCATE COMP "usb_fpga_bd_dp" SITE "D15"; # single-ended bidirectional
|
|
LOCATE COMP "usb_fpga_bd_dn" SITE "E15";
|
|
IOBUF PORT "usb_fpga_bd_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "usb_fpga_bd_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
LOCATE COMP "usb_fpga_pu_dp" SITE "B12"; # pull up/down control
|
|
LOCATE COMP "usb_fpga_pu_dn" SITE "C12";
|
|
IOBUF PORT "usb_fpga_pu_dp" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
IOBUF PORT "usb_fpga_pu_dn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=16;
|
|
|
|
## JTAG ESP-32 "usb" sheet
|
|
# connected to FT231X and ESP-32
|
|
# commented out because those are dedicated pins, not directly useable as GPIO
|
|
# but could be used by some vendor-specific JTAG bridging (boundary scan) module
|
|
#LOCATE COMP "jtag_tdi" SITE "R5"; # FTDI_nRI FPGA receives
|
|
#LOCATE COMP "jtag_tdo" SITE "V4"; # FTDI_nCTS FPGA transmits
|
|
#LOCATE COMP "jtag_tck" SITE "T5"; # FTDI_nDSR FPGA receives
|
|
#LOCATE COMP "jtag_tms" SITE "U5"; # FTDI_nDCD FPGA receives
|
|
#IOBUF PORT "jtag_tdi" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "jtag_tdo" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "jtag_tck" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#IOBUF PORT "jtag_tms" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## SDRAM "ram" sheet
|
|
LOCATE COMP "sdram_clk" SITE "F19";
|
|
LOCATE COMP "sdram_cke" SITE "F20";
|
|
LOCATE COMP "sdram_csn" SITE "P20";
|
|
LOCATE COMP "sdram_wen" SITE "T20";
|
|
LOCATE COMP "sdram_rasn" SITE "R20";
|
|
LOCATE COMP "sdram_casn" SITE "T19";
|
|
LOCATE COMP "sdram_a[0]" SITE "M20";
|
|
LOCATE COMP "sdram_a[1]" SITE "M19";
|
|
LOCATE COMP "sdram_a[2]" SITE "L20";
|
|
LOCATE COMP "sdram_a[3]" SITE "L19";
|
|
LOCATE COMP "sdram_a[4]" SITE "K20";
|
|
LOCATE COMP "sdram_a[5]" SITE "K19";
|
|
LOCATE COMP "sdram_a[6]" SITE "K18";
|
|
LOCATE COMP "sdram_a[7]" SITE "J20";
|
|
LOCATE COMP "sdram_a[8]" SITE "J19";
|
|
LOCATE COMP "sdram_a[9]" SITE "H20";
|
|
LOCATE COMP "sdram_a[10]" SITE "N19";
|
|
LOCATE COMP "sdram_a[11]" SITE "G20";
|
|
LOCATE COMP "sdram_a[12]" SITE "G19";
|
|
LOCATE COMP "sdram_ba[0]" SITE "P19";
|
|
LOCATE COMP "sdram_ba[1]" SITE "N20";
|
|
LOCATE COMP "sdram_dqm[0]" SITE "U19";
|
|
LOCATE COMP "sdram_dqm[1]" SITE "E20";
|
|
LOCATE COMP "sdram_d[0]" SITE "J16";
|
|
LOCATE COMP "sdram_d[1]" SITE "L18";
|
|
LOCATE COMP "sdram_d[2]" SITE "M18";
|
|
LOCATE COMP "sdram_d[3]" SITE "N18";
|
|
LOCATE COMP "sdram_d[4]" SITE "P18";
|
|
LOCATE COMP "sdram_d[5]" SITE "T18";
|
|
LOCATE COMP "sdram_d[6]" SITE "T17";
|
|
LOCATE COMP "sdram_d[7]" SITE "U20";
|
|
LOCATE COMP "sdram_d[8]" SITE "E19";
|
|
LOCATE COMP "sdram_d[9]" SITE "D20";
|
|
LOCATE COMP "sdram_d[10]" SITE "D19";
|
|
LOCATE COMP "sdram_d[11]" SITE "C20";
|
|
LOCATE COMP "sdram_d[12]" SITE "E18";
|
|
LOCATE COMP "sdram_d[13]" SITE "F18";
|
|
LOCATE COMP "sdram_d[14]" SITE "J18";
|
|
LOCATE COMP "sdram_d[15]" SITE "J17";
|
|
IOBUF PORT "sdram_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_cke" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_csn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_wen" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_rasn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_casn" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_a[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_ba[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_ba[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_dqm[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_dqm[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[1]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[2]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[3]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[4]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[5]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[6]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[7]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[8]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[9]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[10]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[11]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[12]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[13]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[14]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "sdram_d[15]" PULLMODE=NONE IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
# GPDI differential interface (Video) "gpdi" sheet
|
|
LOCATE COMP "gpdi_dp[0]" SITE "A16"; # Blue +
|
|
LOCATE COMP "gpdi_dn[0]" SITE "B16"; # Blue -
|
|
LOCATE COMP "gpdi_dp[1]" SITE "A14"; # Green +
|
|
LOCATE COMP "gpdi_dn[1]" SITE "C14"; # Green -
|
|
LOCATE COMP "gpdi_dp[2]" SITE "A12"; # Red +
|
|
LOCATE COMP "gpdi_dn[2]" SITE "A13"; # Red -
|
|
LOCATE COMP "gpdi_dp[3]" SITE "A17"; # Clock +
|
|
LOCATE COMP "gpdi_dn[3]" SITE "B18"; # Clock -
|
|
LOCATE COMP "gpdi_ethp" SITE "A19"; # Ethernet +
|
|
LOCATE COMP "gpdi_ethn" SITE "B20"; # Ethernet -
|
|
LOCATE COMP "gpdi_cec" SITE "A18";
|
|
LOCATE COMP "gpdi_sda" SITE "B19"; # I2C shared with RTC
|
|
LOCATE COMP "gpdi_scl" SITE "E12"; # I2C shared with RTC C12->E12
|
|
IOBUF PORT "gpdi_dp[0]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dn[0]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dp[1]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dn[1]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dp[2]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dn[2]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dp[3]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_dn[3]" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_ethp" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_ethn" IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_cec" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_sda" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
IOBUF PORT "gpdi_scl" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
# GPIO (default single-ended) "gpio", "ram", "gpdi" sheet
|
|
# Physical connector pins:
|
|
# *** when FEMALE ANGLED (90 deg PMOD) soldered ***
|
|
# Jm_n- = Jm_n, Jm_n+ = Jm_n+1
|
|
# example: J1_5- is J1_5 phsyical, J1_5+ is J1_6 physical
|
|
# *** when MALE VERTICAL soldered ***
|
|
# Jm_n+ = Jm_n, Jm_n- = Jm_n+1
|
|
# example: J1_5+ is J1_5 physical, J1_5- is J1_6 physical
|
|
# Pins enumerated gp[0-27], gn[0-27].
|
|
# With differential mode enabled on Lattice,
|
|
# gp[] (+) are used, gn[] (-) are ignored from design
|
|
# as they handle inverted signal by default.
|
|
# To enable differential, rename LVCMOS33->LVCMOS33D
|
|
# To enable clock i/o, add this (example):
|
|
#FREQUENCY PORT "gp[12]" 25.00 MHZ;
|
|
LOCATE COMP "gp[0]" SITE "B11"; # J1_5+ GP0 PCLK
|
|
LOCATE COMP "gn[0]" SITE "C11"; # J1_5- GN0 PCLK
|
|
LOCATE COMP "gp[1]" SITE "A10"; # J1_7+ GP1 PCLK
|
|
LOCATE COMP "gn[1]" SITE "A11"; # J1_7- GN1 PCLK
|
|
LOCATE COMP "gp[2]" SITE "A9"; # J1_9+ GP2 GR_PCLK
|
|
LOCATE COMP "gn[2]" SITE "B10"; # J1_9- GN2 GR_PCLK
|
|
LOCATE COMP "gp[3]" SITE "B9"; # J1_11+ GP3
|
|
LOCATE COMP "gn[3]" SITE "C10"; # J1_11- GN3
|
|
LOCATE COMP "gp[4]" SITE "A7"; # J1_13+ GP4
|
|
LOCATE COMP "gn[4]" SITE "A8"; # J1_13- GN4
|
|
LOCATE COMP "gp[5]" SITE "C8"; # J1_15+ GP5
|
|
LOCATE COMP "gn[5]" SITE "B8"; # J1_15- GN5
|
|
LOCATE COMP "gp[6]" SITE "C6"; # J1_17+ GP6
|
|
LOCATE COMP "gn[6]" SITE "C7"; # J1_17- GN6
|
|
IOBUF PORT "gp[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[0]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[1]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[2]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[3]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[4]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[5]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[6]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
LOCATE COMP "gp[7]" SITE "A6"; # J1_23+ GP7
|
|
LOCATE COMP "gn[7]" SITE "B6"; # J1_23- GN7
|
|
LOCATE COMP "gp[8]" SITE "A4"; # J1_25+ GP8
|
|
LOCATE COMP "gn[8]" SITE "A5"; # J1_25- GN8 DIFF
|
|
LOCATE COMP "gp[9]" SITE "A2"; # J1_27+ GP9 DIFF
|
|
LOCATE COMP "gn[9]" SITE "B1"; # J1_27- GN9 DIFF
|
|
LOCATE COMP "gp[10]" SITE "C4"; # J1_29+ GP10 DIFF
|
|
LOCATE COMP "gn[10]" SITE "B4"; # J1_29- GN10 DIFF
|
|
LOCATE COMP "gp[11]" SITE "F4"; # J1_31+ GP11 DIFF WIFI_GPIO26
|
|
LOCATE COMP "gn[11]" SITE "E3"; # J1_31- GN11 DIFF WIFI_GPIO25
|
|
LOCATE COMP "gp[12]" SITE "G3"; # J1_33+ GP12 DIFF WIFI_GPIO33 PCLK
|
|
LOCATE COMP "gn[12]" SITE "F3"; # J1_33- GN12 DIFF WIFI_GPIO32 PCLK
|
|
LOCATE COMP "gp[13]" SITE "H4"; # J1_35+ GP13 DIFF WIFI_GPIO35
|
|
LOCATE COMP "gn[13]" SITE "G5"; # J1_35- GN13 DIFF WIFI_GPIO34
|
|
IOBUF PORT "gp[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[7]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[8]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[9]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[10]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[11]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[12]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[13]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
LOCATE COMP "gp[14]" SITE "U18"; # J2_5+ GP14 DIFF ADC1
|
|
LOCATE COMP "gn[14]" SITE "U17"; # J2_5- GN14 DIFF ADC0
|
|
LOCATE COMP "gp[15]" SITE "N17"; # J2_7+ GP15 DIFF ADC3
|
|
LOCATE COMP "gn[15]" SITE "P16"; # J2_7- GN15 DIFF ADC2
|
|
LOCATE COMP "gp[16]" SITE "N16"; # J2_9+ GP16 DIFF ADC5
|
|
LOCATE COMP "gn[16]" SITE "M17"; # J2_9- GN16 DIFF ADC4
|
|
LOCATE COMP "gp[17]" SITE "L16"; # J2_11+ GP17 DIFF ADC7 GR_PCLK
|
|
LOCATE COMP "gn[17]" SITE "L17"; # J2_11- GN17 DIFF ADC6
|
|
LOCATE COMP "gp[18]" SITE "H18"; # J2_13+ GP18 DIFF
|
|
LOCATE COMP "gn[18]" SITE "H17"; # J2_13- GN18 DIFF
|
|
LOCATE COMP "gp[19]" SITE "F17"; # J2_15+ GP19 DIFF
|
|
LOCATE COMP "gn[19]" SITE "G18"; # J2_15- GN19 DIFF
|
|
LOCATE COMP "gp[20]" SITE "D18"; # J2_17+ GP20 DIFF
|
|
LOCATE COMP "gn[20]" SITE "E17"; # J2_17- GN20 DIFF
|
|
IOBUF PORT "gp[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[14]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[15]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[16]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[17]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[18]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[19]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[20]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
LOCATE COMP "gp[21]" SITE "C18"; # J2_23+ GP21 DIFF
|
|
LOCATE COMP "gn[21]" SITE "D17"; # J2_23- GN21 DIFF
|
|
LOCATE COMP "gp[22]" SITE "B15"; # J2_25+ GP22
|
|
LOCATE COMP "gn[22]" SITE "C15"; # J2_25- GN22
|
|
LOCATE COMP "gp[23]" SITE "B17"; # J2_27+ GP23
|
|
LOCATE COMP "gn[23]" SITE "C17"; # J2_27- GN23
|
|
LOCATE COMP "gp[24]" SITE "C16"; # J2_29+ GP24
|
|
LOCATE COMP "gn[24]" SITE "D16"; # J2_29- GN24
|
|
LOCATE COMP "gp[25]" SITE "D14"; # J2_31+ GP25
|
|
LOCATE COMP "gn[25]" SITE "E14"; # J2_31- GN25
|
|
LOCATE COMP "gp[26]" SITE "B13"; # J2_33+ GP26
|
|
LOCATE COMP "gn[26]" SITE "C13"; # J2_33- GN26
|
|
LOCATE COMP "gp[27]" SITE "D13"; # J2_35+ GP27
|
|
LOCATE COMP "gn[27]" SITE "E13"; # J2_35- GN27
|
|
IOBUF PORT "gp[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[21]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[22]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[23]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[24]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[25]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[26]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gp[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
IOBUF PORT "gn[27]" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=8;
|
|
|
|
## PROGRAMN (reload bitstream from FLASH, exit from bootloader)
|
|
# PCB v2.0.5 and higher
|
|
LOCATE COMP "user_programn" SITE "M4";
|
|
IOBUF PORT "user_programn" PULLMODE=UP IO_TYPE=LVCMOS33 DRIVE=4;
|
|
|
|
## SHUTDOWN "power", "ram" sheet (connected from PCB v1.7.5)
|
|
# on PCB v1.7 shutdown is not connected to FPGA
|
|
LOCATE COMP "shutdown" SITE "G16"; # FPGA receives
|
|
IOBUF PORT "shutdown" PULLMODE=DOWN IO_TYPE=LVCMOS33 DRIVE=4;
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build*
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
# exit ################### DEBUG DEBUG DEBUG
|
|
|
|
yosys -p 'scratchpad -copy abc9.script.flow3 abc9.script; synth_ecp5 -abc9 -json build.json' build.v
|
|
|
|
nextpnr-ecp5 --85k --package CABGA381 --freq 25 --json build.json --textcfg build.config --lpf $BOARD_DIR/ulx3s.lpf --timing-allow-fail
|
|
|
|
sed -i '/.sysconfig/d' build.config
|
|
|
|
ecppack --compress --svf-rowsize 100000 --svf build.svf build.config build.bit
|
|
|
|
fujprog build.bit
|
|
{
|
|
"name": "ulx3s",
|
|
"variants": [
|
|
{
|
|
"name": "85k",
|
|
"framework" : "ulx3s.v",
|
|
"pins": [
|
|
{"set" : "basic"},
|
|
{"set" : "buttons","define" : "BUTTONS=1"},
|
|
{"set" : "vga", "define" : "VGA=1"},
|
|
{"set" : "oled", "define" : "OLED=1"},
|
|
{"set" : "sdram", "define" : "SDRAM=1"},
|
|
{"set" : "sdcard", "define" : "SDCARD=1"},
|
|
{"set" : "hdmi", "define" : "HDMI=1"},
|
|
{"set" : "gpio", "define" : "GPIO=1"},
|
|
{"set" : "audio", "define" : "AUDIO=1"},
|
|
{"set" : "uart", "define" : "UART=1"},
|
|
{"set" : "uart2", "define" : "UART2=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "trellis",
|
|
"tool_options": [
|
|
{
|
|
"yosys_synth_options": ["-abc9"],
|
|
"nextpnr_options": ["--85k", "--freq 25", "--package CABGA381", "--timing-allow-fail"],
|
|
"pnr": "next"
|
|
}
|
|
],
|
|
"bitstream" : "build.bit",
|
|
"constraints": [{"name": "ulx3s.lpf", "file_type": "LPF"}],
|
|
"program": [{"cmd" : "fujprog", "args" : "build.bit"}]
|
|
},
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "ulx3s.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"buttons" : [
|
|
{
|
|
"name": "btns",
|
|
"type": "uint7",
|
|
"io": "input"
|
|
}
|
|
],
|
|
"audio" : [
|
|
{
|
|
"name": "audio_l",
|
|
"type": "uint4",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "audio_r",
|
|
"type": "uint4",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"oled": [
|
|
{
|
|
"name": "oled_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_mosi",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_dc",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_resn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_csn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"sdcard": [
|
|
{
|
|
"name": "sd_csn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sd_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sd_mosi",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sd_miso",
|
|
"type": "uint1",
|
|
"io": "input"
|
|
}
|
|
],
|
|
"sdram": [
|
|
{
|
|
"name": "sdram_dq",
|
|
"type": "uint16",
|
|
"io": "inout"
|
|
},
|
|
{
|
|
"name": "sdram_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cle",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_dqm",
|
|
"type": "uint2",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_we",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cas",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ras",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ba",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_a",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"hdmi": [
|
|
{
|
|
"name": "gpdi_dq",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "gpdi_dn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"gpio": [
|
|
{
|
|
"name": "gp",
|
|
"type": "uint28",
|
|
"io": "inout"
|
|
},
|
|
{
|
|
"name": "gn",
|
|
"type": "uint28",
|
|
"io": "inout"
|
|
}
|
|
],
|
|
"uart": [
|
|
{
|
|
"name": "uart_tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "uart_rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"uart2": [
|
|
{
|
|
"name": "uart2_tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "uart2_rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define ICESTICK 1
|
|
`default_nettype none
|
|
$$ICESTICK=1
|
|
$$HARDWARE=1
|
|
$$NUM_LEDS=5
|
|
$$VGA=1
|
|
$$color_depth=6
|
|
$$color_max =63
|
|
$$config['bram_wenable_width'] = 'data'
|
|
$$config['dualport_bram_wenable0_width'] = 'data'
|
|
$$config['dualport_bram_wenable1_width'] = 'data'
|
|
$$config['simple_dualport_bram_wenable0_width'] = 'data'
|
|
$$config['simple_dualport_bram_wenable1_width'] = 'data'
|
|
|
|
module top(
|
|
output D1,
|
|
output D2,
|
|
output D3,
|
|
output D4,
|
|
output D5,
|
|
`ifdef OLED
|
|
output BR3,
|
|
output BR4,
|
|
output BR5,
|
|
output BR6,
|
|
output BR7,
|
|
`endif
|
|
`ifdef VGA
|
|
output PMOD1, // r0
|
|
output PMOD2, // r1
|
|
output PMOD3, // r2
|
|
output PMOD4, // r3
|
|
output PMOD8, // r4
|
|
output PMOD9, // r5
|
|
|
|
output TR10, // g0
|
|
output TR9, // g1
|
|
output TR8, // g2
|
|
output TR7, // g3
|
|
output TR6, // g4
|
|
output TR5, // g5
|
|
|
|
output BR10, // b0
|
|
output BR9, // b1
|
|
output BR8, // b2
|
|
output BR7, // b3
|
|
output BR6, // b4
|
|
output BR5, // b5
|
|
|
|
output PMOD7, // hs
|
|
output PMOD10, // vs
|
|
`endif
|
|
input CLK
|
|
);
|
|
|
|
wire [4:0] __main_leds;
|
|
|
|
`ifdef OLED
|
|
wire __main_oled_clk;
|
|
wire __main_oled_mosi;
|
|
wire __main_oled_csn;
|
|
wire __main_oled_resn;
|
|
wire __main_oled_dc;
|
|
`endif
|
|
|
|
`ifdef VGA
|
|
wire __main_out_vga_hs;
|
|
wire __main_out_vga_vs;
|
|
wire __main_out_vga_v0;
|
|
wire [5:0] __main_out_vga_r;
|
|
wire [5:0] __main_out_vga_g;
|
|
wire [5:0] __main_out_vga_b;
|
|
`endif
|
|
|
|
// the init sequence pauses for some cycles
|
|
// waiting for BRAM init to stabalize
|
|
// this is a known issue with ice40 FPGAs
|
|
// https://github.com/YosysHQ/icestorm/issues/76
|
|
|
|
reg ready = 0;
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge CLK) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 32'b11111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.clock(CLK),
|
|
.reset(RST_d),
|
|
.out_leds(__main_leds),
|
|
`ifdef OLED
|
|
.out_oled_mosi(__main_oled_mosi),
|
|
.out_oled_clk(__main_oled_clk),
|
|
.out_oled_csn(__main_oled_csn),
|
|
.out_oled_dc(__main_oled_dc),
|
|
.out_oled_resn(__main_oled_resn),
|
|
`endif
|
|
`ifdef VGA
|
|
.out_video_hs(__main_out_vga_hs),
|
|
.out_video_vs(__main_out_vga_vs),
|
|
.out_video_r(__main_out_vga_r),
|
|
.out_video_g(__main_out_vga_g),
|
|
.out_video_b(__main_out_vga_b),
|
|
`endif
|
|
.in_run(run_main)
|
|
);
|
|
|
|
assign D1 = __main_leds[0+:1];
|
|
assign D2 = __main_leds[1+:1];
|
|
assign D3 = __main_leds[2+:1];
|
|
assign D4 = __main_leds[3+:1];
|
|
assign D5 = __main_leds[4+:1];
|
|
|
|
// OLED
|
|
|
|
`ifdef OLED
|
|
|
|
assign BR3 = __main_oled_mosi;
|
|
assign BR4 = __main_oled_clk;
|
|
assign BR5 = __main_oled_csn;
|
|
assign BR6 = __main_oled_dc;
|
|
assign BR7 = __main_oled_resn;
|
|
|
|
`endif
|
|
|
|
// VGA
|
|
|
|
`ifdef VGA
|
|
|
|
assign PMOD1 = __main_out_vga_r[5+:1];
|
|
assign PMOD2 = __main_out_vga_r[4+:1];
|
|
assign PMOD3 = __main_out_vga_r[3+:1];
|
|
assign PMOD4 = __main_out_vga_r[2+:1];
|
|
assign PMOD8 = __main_out_vga_r[1+:1];
|
|
assign PMOD9 = __main_out_vga_r[0+:1];
|
|
|
|
assign TR10 = __main_out_vga_g[5+:1];
|
|
assign TR9 = __main_out_vga_g[4+:1];
|
|
assign TR8 = __main_out_vga_g[3+:1];
|
|
assign TR7 = __main_out_vga_g[2+:1];
|
|
assign TR6 = __main_out_vga_g[1+:1];
|
|
assign TR5 = __main_out_vga_g[0+:1];
|
|
|
|
assign BR10 = __main_out_vga_b[5+:1];
|
|
assign BR9 = __main_out_vga_b[4+:1];
|
|
assign BR8 = __main_out_vga_b[3+:1];
|
|
assign BR7 = __main_out_vga_b[2+:1];
|
|
assign BR6 = __main_out_vga_b[1+:1];
|
|
assign BR5 = __main_out_vga_b[0+:1];
|
|
|
|
assign PMOD7 = __main_out_vga_hs;
|
|
assign PMOD10 = __main_out_vga_vs;
|
|
|
|
`endif
|
|
|
|
|
|
endmodule
|
|
# -----------------------------------------------------------------------------
|
|
#- Icestick constraint file (.pcf)
|
|
#- By Juan Gonzalez (Obijuan)
|
|
#- April - 2016
|
|
#- GPL license
|
|
# -----------------------------------------------------------------------------
|
|
# -- Pinout: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/images/icestick_pinout.png
|
|
# -- Guide: https://github.com/Obijuan/open-fpga-verilog-tutorial/blob/master/tutorial/doc/icestickusermanual.pdf
|
|
|
|
# -- Icestick leds map
|
|
#
|
|
# D1
|
|
# D4 D5 D2
|
|
# D3
|
|
#
|
|
# -- D1-D4: Red leds
|
|
# -- D5: green led
|
|
|
|
|
|
# ------------ Red leds ------------------------------------------------------
|
|
set_io --warn-no-port D1 99
|
|
set_io --warn-no-port D2 98
|
|
set_io --warn-no-port D3 97
|
|
set_io --warn-no-port D4 96
|
|
|
|
# ------------ Green led -----------------------------------------------------
|
|
set_io --warn-no-port D5 95
|
|
|
|
# ------------ IrDA ----------------------------------------------------------
|
|
set_io --warn-no-port IrDA_TX 105
|
|
set_io --warn-no-port IrDA_RX 106
|
|
|
|
#-- SD = 0, enable IrDA
|
|
set_io --warn-no-port SD 107
|
|
|
|
# ------------ PMOD connector ------------------------------------------------
|
|
#
|
|
# Pmod standar numeration (Oriented according the icestick, with the
|
|
# usb connector pointing to the left and IRda to the right)
|
|
#
|
|
# --------
|
|
# | 12 6 |
|
|
# | 11 5 |
|
|
# | 10 4 |
|
|
# | 9 3 |
|
|
# | 8 2 |
|
|
# | 7 1 | <
|
|
# --------
|
|
#
|
|
# FPGA pins:
|
|
#
|
|
# ----------
|
|
# | 3V3 3V3 |
|
|
# | GND GND |
|
|
# | 91 81 |
|
|
# | 90 80 |
|
|
# | 88 79 |
|
|
# | 87 78 | <
|
|
# ----------
|
|
#
|
|
set_io --warn-no-port PMOD1 78
|
|
set_io --warn-no-port PMOD2 79
|
|
set_io --warn-no-port PMOD3 80
|
|
set_io --warn-no-port PMOD4 81
|
|
set_io --warn-no-port PMOD7 87
|
|
set_io --warn-no-port PMOD8 88
|
|
set_io --warn-no-port PMOD9 90
|
|
set_io --warn-no-port PMOD10 91
|
|
|
|
# ------------------------ EXPANSION I/O ------------------------------------
|
|
#
|
|
# -- Numeration
|
|
#
|
|
# Top Row (TR):
|
|
# v
|
|
# --------------------------------
|
|
# | 10 9 8 7 6 5 4 3 2 1 |
|
|
# --------------------------------
|
|
#
|
|
# Bottom Row (BR):
|
|
#
|
|
# v
|
|
# --------------------------------
|
|
# | 10 9 8 7 6 5 4 3 2 1 |
|
|
# --------------------------------
|
|
#
|
|
# --- FPGA pins
|
|
#
|
|
# Top Row (TR)
|
|
# v
|
|
# --------------------------------------------------
|
|
# | 119 118 117 116 115 114 113 112 GND 3v3 |
|
|
# --------------------------------------------------
|
|
#
|
|
#
|
|
# Bottom Row (BR)
|
|
#
|
|
# v
|
|
# -------------------------------------------------
|
|
# | 44 45 47 48 56 60 61 62 GND 3v3 |
|
|
# -------------------------------------------------
|
|
#
|
|
# -- Top Row
|
|
set_io --warn-no-port TR3 112
|
|
set_io --warn-no-port TR4 113
|
|
set_io --warn-no-port TR5 114
|
|
set_io --warn-no-port TR6 115
|
|
set_io --warn-no-port TR7 116
|
|
set_io --warn-no-port TR8 117
|
|
set_io --warn-no-port TR9 118
|
|
set_io --warn-no-port TR10 119
|
|
#
|
|
# -- Bottom Row
|
|
set_io --warn-no-port BR3 62
|
|
set_io --warn-no-port BR4 61
|
|
set_io --warn-no-port BR5 60
|
|
set_io --warn-no-port BR6 56
|
|
set_io --warn-no-port BR7 48
|
|
set_io --warn-no-port BR8 47
|
|
set_io --warn-no-port BR9 45
|
|
set_io --warn-no-port BR10 44
|
|
|
|
# -------------------------- SYSTEM CLOCK ------------------------------------
|
|
set_io --warn-no-port CLK 21
|
|
|
|
# -------------------------- FTDI --------------------------------------------
|
|
# --- FTDI 0:
|
|
set_io --warn-no-port RES 66
|
|
set_io --warn-no-port DONE 65
|
|
set_io --warn-no-port SS 71
|
|
set_io --warn-no-port MISO 67
|
|
set_io --warn-no-port MOSI 68
|
|
set_io --warn-no-port SCK 70
|
|
#
|
|
# --- FTDI 1: (Serial port)
|
|
set_io --warn-no-port DCD 1
|
|
set_io --warn-no-port DSR 2
|
|
set_io --warn-no-port DTR 3
|
|
set_io --warn-no-port CTS 4
|
|
set_io --warn-no-port RTS 7
|
|
set_io --warn-no-port TX 8
|
|
set_io --warn-no-port RX 9
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build*
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
if ! type "nextpnr-ice40" > /dev/null; then
|
|
# try arachne-pnr instead
|
|
echo "nextpnr-ice40 not found, trying arachne-pnr instead"
|
|
yosys -q -p "synth_ice40 -blif build.blif" build.v
|
|
arachne-pnr -p $BOARD_DIR/icestick.pcf build.blif -o build.txt
|
|
icepack build.txt build.bin
|
|
else
|
|
yosys -p 'synth_ice40 -top top -json build.json' build.v
|
|
nextpnr-ice40 --hx1k --json build.json --pcf $BOARD_DIR/icestick.pcf --asc build.asc --package tq144 --freq 12
|
|
icepack build.asc build.bin
|
|
fi
|
|
|
|
iceprog build.bin
|
|
{
|
|
"name": "icestick",
|
|
"variants": [
|
|
{
|
|
"name" : "configurable",
|
|
"framework" : "icestick.v",
|
|
"pins" : [
|
|
{"set" : "basic"},
|
|
{"set" : "vga", "define" : "VGA=1"},
|
|
{"set" : "oled", "define" : "OLED=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "icestorm",
|
|
"tool_options": [
|
|
{
|
|
"nextpnr_options": ["--hx1k", "--freq 12", "--package tq144", "--timing-allow-fail"],
|
|
"pnr": "next"
|
|
}
|
|
],
|
|
"bitstream" : "build.bin",
|
|
"constraints": [{"name": "icestick.pcf", "file_type": "PCF"}],
|
|
"program": [{"cmd" : "iceprog", "args" : "build.bin"}]
|
|
},
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "icestick.sh",
|
|
"description": "Custom shell scripts using yosys and nextpnr"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint5",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"oled": [
|
|
{
|
|
"name": "oled_clk",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_mosi",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_csn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_resn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "oled_dc",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
if hash make 2>/dev/null; then
|
|
export MAKE=make
|
|
else
|
|
export MAKE=mingw32-make
|
|
fi
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
|
|
if [[ -z "${VERILATOR_ROOT}" ]]; then
|
|
case "$(uname -s)" in
|
|
Linux)
|
|
unset VERILATOR_ROOT
|
|
;;
|
|
*)
|
|
export VERILATOR_ROOT=$SILICE_DIR/../tools/fpga-binutils/mingw64/
|
|
;;
|
|
esac
|
|
echo "VERILATOR_ROOT is set to ${VERILATOR_ROOT}"
|
|
else
|
|
echo "VERILATOR_ROOT already defined, using its value"
|
|
fi
|
|
|
|
u=$(echo "$1" | sed s:/:__:g | tr -d ".")
|
|
|
|
echo "using directory $u"
|
|
|
|
cd $BUILD_DIR
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
if [[ -z "${VGA}" ]] && [[ -z "${SDRAM}" ]]; then
|
|
VERILATOR_LIB="verilator_bare"
|
|
else
|
|
VERILATOR_LIB="verilator_vga"
|
|
fi
|
|
|
|
echo "using verilator framework $VERILATOR_LIB"
|
|
|
|
verilator -Wno-PINMISSING -Wno-WIDTH -O3 -cc build.v --top-module top
|
|
cd obj_dir
|
|
$MAKE -f Vtop.mk
|
|
$MAKE -f Vtop.mk $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o
|
|
g++ -O3 $SILICE_DIR/../frameworks/verilator/$VERILATOR_LIB.o verilated.o Vtop__ALL.a $SILICE_DIR/../frameworks/verilator/libverilator_silice.a -o ../run_simul
|
|
cd ..
|
|
|
|
./run_simul
|
|
{
|
|
"name": "verilator",
|
|
"variants": [
|
|
{
|
|
"name" : "configurable",
|
|
"framework" : "verilator.v",
|
|
"pins" : [
|
|
{"set" : "basic"},
|
|
{"set" : "vga", "define" : "VGA=1"},
|
|
{"set" : "sdram", "define" : "SDRAM=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "verilator.sh",
|
|
"description": "Simulates with verilator"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"sdram": [
|
|
{
|
|
"name": "sdram_clock",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_dq_i",
|
|
"type": "uint16",
|
|
"io": "input"
|
|
},
|
|
{
|
|
"name": "sdram_dq_o",
|
|
"type": "uint16",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_dq_en",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cle",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_dqm",
|
|
"type": "uint2",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_we",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_cas",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ras",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_ba",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "sdram_a",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define VERILATOR 1
|
|
`define COLOR_DEPTH 6
|
|
`define SDRAM_WORD_WIDTH 16
|
|
|
|
$$VERILATOR = 1
|
|
$$NUM_LEDS = 8
|
|
$$SIMULATION = 1
|
|
$$color_depth = 6
|
|
$$color_max = 63
|
|
|
|
`timescale 1ns / 1ps
|
|
`default_nettype none
|
|
|
|
module top(
|
|
// SDRAM
|
|
output reg sdram_clock,
|
|
output reg sdram_cle,
|
|
output reg [1:0] sdram_dqm,
|
|
output reg sdram_cs,
|
|
output reg sdram_we,
|
|
output reg sdram_cas,
|
|
output reg sdram_ras,
|
|
output reg [1:0] sdram_ba,
|
|
output reg [12:0] sdram_a,
|
|
input [15:0] sdram_dq_i,
|
|
output reg [15:0] sdram_dq_o,
|
|
output reg sdram_dq_en,
|
|
// VGA
|
|
output video_clock,
|
|
output reg [`COLOR_DEPTH-1:0] video_r,
|
|
output reg [`COLOR_DEPTH-1:0] video_g,
|
|
output reg [`COLOR_DEPTH-1:0] video_b,
|
|
output video_hs,
|
|
output video_vs,
|
|
output [5:0] sdram_word_width,
|
|
output [4:0] video_color_depth,
|
|
input clk
|
|
);
|
|
|
|
// this is used by the verilator framework
|
|
// -> to know the output color depth
|
|
assign video_color_depth = `COLOR_DEPTH;
|
|
// -> to know the sdram word width
|
|
assign sdram_word_width = `SDRAM_WORD_WIDTH;
|
|
|
|
wire __main_sdram_clock;
|
|
wire __main_sdram_cle;
|
|
wire [1:0] __main_sdram_dqm;
|
|
wire __main_sdram_cs;
|
|
wire __main_sdram_we;
|
|
wire __main_sdram_cas;
|
|
wire __main_sdram_ras;
|
|
wire [1:0] __main_sdram_ba;
|
|
wire [12:0] __main_sdram_a;
|
|
wire [15:0] __main_sdram_dq_o;
|
|
wire __main_sdram_dq_en;
|
|
|
|
wire __main_video_clock;
|
|
wire [`COLOR_DEPTH-1:0] __main_video_r;
|
|
wire [`COLOR_DEPTH-1:0] __main_video_g;
|
|
wire [`COLOR_DEPTH-1:0] __main_video_b;
|
|
wire __main_video_hs;
|
|
wire __main_video_vs;
|
|
|
|
wire [7:0] __main_leds;
|
|
|
|
// reset
|
|
|
|
reg ready = 0;
|
|
reg [3:0] RST_d;
|
|
reg [3:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 4'b1111;
|
|
end
|
|
end
|
|
|
|
// main
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
wire done_main;
|
|
|
|
M_main __main(
|
|
.clock(clk),
|
|
.reset(RST_d[0]),
|
|
.out_leds(__main_leds),
|
|
`ifdef SDRAM
|
|
.out_sdram_clock(__main_sdram_clock),
|
|
.out_sdram_cle(__main_sdram_cle),
|
|
.out_sdram_dqm(__main_sdram_dqm),
|
|
.out_sdram_cs(__main_sdram_cs),
|
|
.out_sdram_we(__main_sdram_we),
|
|
.out_sdram_cas(__main_sdram_cas),
|
|
.out_sdram_ras(__main_sdram_ras),
|
|
.out_sdram_ba(__main_sdram_ba),
|
|
.out_sdram_a(__main_sdram_a),
|
|
.in_sdram_dq_i(sdram_dq_i),
|
|
.out_sdram_dq_o(__main_sdram_dq_o),
|
|
.out_sdram_dq_en(__main_sdram_dq_en),
|
|
`endif
|
|
`ifdef VGA
|
|
.out_video_clock(__main_video_clock),
|
|
.out_video_r(__main_video_r),
|
|
.out_video_g(__main_video_g),
|
|
.out_video_b(__main_video_b),
|
|
.out_video_hs(__main_video_hs),
|
|
.out_video_vs(__main_video_vs),
|
|
`endif
|
|
.in_run(run_main),
|
|
.out_done(done_main)
|
|
);
|
|
|
|
assign sdram_clock = __main_sdram_clock;
|
|
assign sdram_cle = __main_sdram_cle;
|
|
assign sdram_dqm = __main_sdram_dqm;
|
|
assign sdram_cs = __main_sdram_cs;
|
|
assign sdram_we = __main_sdram_we;
|
|
assign sdram_cas = __main_sdram_cas;
|
|
assign sdram_ras = __main_sdram_ras;
|
|
assign sdram_ba = __main_sdram_ba;
|
|
assign sdram_a = __main_sdram_a;
|
|
assign sdram_dq_o = __main_sdram_dq_o;
|
|
assign sdram_dq_en = __main_sdram_dq_en;
|
|
|
|
assign video_clock = __main_video_clock;
|
|
assign video_r = __main_video_r;
|
|
assign video_g = __main_video_g;
|
|
assign video_b = __main_video_b;
|
|
assign video_hs = __main_video_hs;
|
|
assign video_vs = __main_video_vs;
|
|
|
|
always @* begin
|
|
if (done_main && !RST_d[0]) $finish;
|
|
end
|
|
|
|
endmodule
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/:$SILICE_DIR
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm -rf build* *.rdf *.sty impl
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
cat << EOF > build.tcl
|
|
prj_create -name "build" -impl "impl" -dev LIFCL-40-9BG400C
|
|
prj_set_impl_opt {include path} {""}
|
|
prj_add_source "build.v" -work work
|
|
prj_add_source "$BOARD_DIR/crosslink_nx_evn.pdc" -work work
|
|
prj_set_impl_opt top "top"
|
|
prj_save
|
|
prj_run Synthesis -impl impl -forceOne
|
|
prj_run Map -impl impl
|
|
prj_run PAR -impl impl
|
|
prj_run Export -impl impl -task Bitgen
|
|
prj_close
|
|
EOF
|
|
|
|
radiantc build.tcl > toto.log 2>&1 # toto.log - French touch ;-)
|
|
|
|
openFPGALoader impl/build_impl.bit
|
|
# ----------------------------------------------------------------------------
|
|
#
|
|
# CrosslinkNX evn constraint file (.pdc)
|
|
# Link
|
|
# https://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/CrossLink-NXEvaluationBoard
|
|
#
|
|
# ----------------------------------------------------------------------------
|
|
|
|
# -------------------------- SYSTEM CLOCK ------------------------------------
|
|
ldc_set_location -site {L13} [get_ports CLK]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports CLK]
|
|
|
|
ldc_set_location -site {C12} [get_ports OSC_P]
|
|
ldc_set_location -site {C11} [get_ports OSC_N]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_P]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_N]
|
|
|
|
# ------------------------------ UART ----------------------------------------
|
|
ldc_set_location -site {F18} [get_ports RX]
|
|
ldc_set_location -site {F16} [get_ports TX]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_P]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33D} [get_ports OSC_N]
|
|
|
|
# ------------------------- LED ----------------------------------------------
|
|
ldc_set_location -site {E17} [get_ports LED0]
|
|
ldc_set_location -site {F13} [get_ports LED1]
|
|
ldc_set_location -site {G13} [get_ports LED2]
|
|
ldc_set_location -site {F14} [get_ports LED3]
|
|
ldc_set_location -site {L16} [get_ports LED4]
|
|
ldc_set_location -site {L15} [get_ports LED5]
|
|
ldc_set_location -site {L20} [get_ports LED6]
|
|
ldc_set_location -site {L19} [get_ports LED7]
|
|
ldc_set_location -site {R17} [get_ports LED8]
|
|
ldc_set_location -site {R18} [get_ports LED9]
|
|
ldc_set_location -site {U20} [get_ports LED10]
|
|
ldc_set_location -site {T20} [get_ports LED11]
|
|
ldc_set_location -site {W20} [get_ports LED12]
|
|
ldc_set_location -site {V20} [get_ports LED13]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED0]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED1]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED2]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED3]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED4]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED5]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED6]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED7]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED8]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED9]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED10]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED11]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED12]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports LED13]
|
|
|
|
# ------------------------- Button -------------------------------------------
|
|
ldc_set_location -site {G14} [get_ports SW2]
|
|
ldc_set_location -site {G15} [get_ports SW3]
|
|
ldc_set_location -site {G19} [get_ports SW4]
|
|
ldc_set_location -site {E11} [get_ports SW5]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW2]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW3]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW4]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SW5]
|
|
|
|
# ----------------------- DIP Switch -----------------------------------------
|
|
ldc_set_location -site {N14} [get_ports SWITCH0]
|
|
ldc_set_location -site {M14} [get_ports SWITCH1]
|
|
ldc_set_location -site {M16} [get_ports SWITCH2]
|
|
ldc_set_location -site {M15} [get_ports SWITCH3]
|
|
ldc_set_location -site {N15} [get_ports SWITCH4]
|
|
ldc_set_location -site {N16} [get_ports SWITCH5]
|
|
ldc_set_location -site {M17} [get_ports SWITCH6]
|
|
ldc_set_location -site {M18} [get_ports SWITCH7]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH0]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH1]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH2]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH3]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH4]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH5]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH6]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports SWITCH7]
|
|
|
|
# --------------------------- SPI Flash --------------------------------------
|
|
ldc_set_location -site {} [get_ports FLASH_SCK]
|
|
ldc_set_location -site {} [get_ports FLASH_SSB]
|
|
ldc_set_location -site {} [get_ports FLASH_IO0]
|
|
ldc_set_location -site {} [get_ports FLASH_IO1]
|
|
ldc_set_location -site {} [get_ports FLASH_IO2]
|
|
ldc_set_location -site {} [get_ports FLASH_IO3]
|
|
|
|
# ------------ PMOD0 connector --------- -------------------------------------
|
|
ldc_set_location -site {D10} [get_ports PMOD0_1 ]
|
|
ldc_set_location -site {D9} [get_ports PMOD0_2 ]
|
|
ldc_set_location -site {D7} [get_ports PMOD0_3 ]
|
|
ldc_set_location -site {D8} [get_ports PMOD0_4 ]
|
|
ldc_set_location -site {D6} [get_ports PMOD0_7 ]
|
|
ldc_set_location -site {D5} [get_ports PMOD0_8 ]
|
|
ldc_set_location -site {D4} [get_ports PMOD0_9 ]
|
|
ldc_set_location -site {D3} [get_ports PMOD0_10]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_1 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_2 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_3 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_4 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_7 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_8 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_9 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD0_10]
|
|
|
|
# ------------ PMOD1 connector -----------------------------------------------
|
|
ldc_set_location -site {E10} [get_ports PMOD1_1 ]
|
|
ldc_set_location -site {E9} [get_ports PMOD1_2 ]
|
|
ldc_set_location -site {E7} [get_ports PMOD1_3 ]
|
|
ldc_set_location -site {E8} [get_ports PMOD1_4 ]
|
|
ldc_set_location -site {E4} [get_ports PMOD1_7 ]
|
|
ldc_set_location -site {E3} [get_ports PMOD1_8 ]
|
|
ldc_set_location -site {E2} [get_ports PMOD1_9 ]
|
|
ldc_set_location -site {F1} [get_ports PMOD1_10]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_1 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_2 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_3 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_4 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_7 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_8 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_9 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD1_10]
|
|
|
|
# ------------ PMOD2 connector -----------------------------------------------
|
|
ldc_set_location -site { J2} [get_ports PMOD2_1 ]
|
|
ldc_set_location -site { J1} [get_ports PMOD2_2 ]
|
|
ldc_set_location -site { K2} [get_ports PMOD2_3 ]
|
|
ldc_set_location -site { K1} [get_ports PMOD2_4 ]
|
|
ldc_set_location -site { K3} [get_ports PMOD2_7 ]
|
|
ldc_set_location -site { K4} [get_ports PMOD2_8 ]
|
|
ldc_set_location -site {D17} [get_ports PMOD2_9 ]
|
|
ldc_set_location -site {E18} [get_ports PMOD2_10]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_1 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_2 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_3 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_4 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_7 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_8 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_9 ]
|
|
ldc_set_port -iobuf {IO_TYPE=LVCMOS33} [get_ports PMOD2_10]
|
|
|
|
ldc_set_sysconfig {CONFIG_MODE=SPI_SERIAL MCCLK_FREQ=3.5}
|
|
`define CROSSLINKNX_EVN 1
|
|
$$CROSSLINKNX_EVN=1
|
|
$$HARDWARE=1
|
|
$$NUM_LEDS=5
|
|
$$VGA=1
|
|
$$color_depth=6
|
|
$$color_max =63
|
|
$$config['bram_wenable_width'] = 'data'
|
|
$$config['dualport_bram_wenable0_width'] = 'data'
|
|
$$config['dualport_bram_wenable1_width'] = 'data'
|
|
|
|
module top(
|
|
output LED0,
|
|
output LED1,
|
|
output LED2,
|
|
output LED3,
|
|
output LED4,
|
|
`ifdef VGA
|
|
output PMOD0_1, // r0
|
|
output PMOD0_2, // r1
|
|
output PMOD0_3, // r2
|
|
output PMOD0_4, // r3
|
|
|
|
output PMOD0_7, // b0
|
|
output PMOD0_8, // b1
|
|
output PMOD0_9, // b2
|
|
output PMOD0_10,// b3
|
|
|
|
output PMOD1_1, // g0
|
|
output PMOD1_2, // g1
|
|
output PMOD1_3, // g2
|
|
output PMOD1_4, // g3
|
|
|
|
output PMOD1_7, // hs
|
|
output PMOD1_8, // vs
|
|
`endif
|
|
input CLK
|
|
);
|
|
|
|
wire [4:0] __main_leds;
|
|
|
|
// clock from design is used in case
|
|
// it relies on a PLL: in such cases
|
|
// we cannot use the clock fed into
|
|
// the PLL here
|
|
wire design_clk;
|
|
|
|
`ifdef VGA
|
|
wire __main_out_vga_hs;
|
|
wire __main_out_vga_vs;
|
|
wire [5:0] __main_out_vga_r;
|
|
wire [5:0] __main_out_vga_g;
|
|
wire [5:0] __main_out_vga_b;
|
|
`endif
|
|
|
|
BB u0_BB (.B(CLK),
|
|
.I(1'b0),
|
|
.T(1'b1),
|
|
.O(clk_s)
|
|
);
|
|
|
|
reg ready = 0;
|
|
reg [31:0] RST_d;
|
|
reg [31:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge design_clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 32'b111111111111111111111111111111;
|
|
end
|
|
end
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.clock(clk_s),
|
|
.out_clock(design_clk),
|
|
.reset(RST_d[0]),
|
|
.out_leds(__main_leds),
|
|
`ifdef VGA
|
|
.out_video_hs(__main_out_vga_hs),
|
|
.out_video_vs(__main_out_vga_vs),
|
|
.out_video_r(__main_out_vga_r),
|
|
.out_video_g(__main_out_vga_g),
|
|
.out_video_b(__main_out_vga_b),
|
|
`endif
|
|
.in_run(run_main)
|
|
);
|
|
|
|
assign LED0 = __main_leds[0+:1];
|
|
assign LED1 = __main_leds[1+:1];
|
|
assign LED2 = __main_leds[2+:1];
|
|
assign LED3 = __main_leds[3+:1];
|
|
assign LED4 = __main_leds[4+:1];
|
|
|
|
// VGA
|
|
|
|
`ifdef VGA
|
|
|
|
assign PMOD0_1 = __main_out_vga_r[2+:1];
|
|
assign PMOD0_2 = __main_out_vga_r[3+:1];
|
|
assign PMOD0_3 = __main_out_vga_r[4+:1];
|
|
assign PMOD0_4 = __main_out_vga_r[5+:1];
|
|
|
|
assign PMOD0_7 = __main_out_vga_b[2+:1];
|
|
assign PMOD0_8 = __main_out_vga_b[3+:1];
|
|
assign PMOD0_9 = __main_out_vga_b[4+:1];
|
|
assign PMOD0_10 = __main_out_vga_b[5+:1];
|
|
|
|
assign PMOD1_1 = __main_out_vga_g[2+:1];
|
|
assign PMOD1_2 = __main_out_vga_g[3+:1];
|
|
assign PMOD1_3 = __main_out_vga_g[4+:1];
|
|
assign PMOD1_4 = __main_out_vga_g[5+:1];
|
|
|
|
assign PMOD1_7 = __main_out_vga_hs;
|
|
assign PMOD1_8 = __main_out_vga_vs;
|
|
|
|
`endif
|
|
|
|
endmodule
|
|
{
|
|
"name": "crosslink_nx_evn",
|
|
"variants": [
|
|
{
|
|
"name": "configurable",
|
|
"framework" : "crosslink_nx_evn.v",
|
|
"pins": [
|
|
{"set" : "basic"},
|
|
{"set" : "vga", "define" : "VGA=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "radiant",
|
|
"tool_options": [
|
|
{
|
|
"part": "LIFCL-40-9BG400C"
|
|
}
|
|
],
|
|
"bitstream" : "impl/build_impl.bit",
|
|
"constraints": [{"name": "crosslink_nx_evn.pdc", "file_type": "PDC"}],
|
|
"program": [{"cmd" : "openFPGALoader", "args" : "impl/build_impl.bit"}]
|
|
},
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "crosslink_nx_evn.sh",
|
|
"description": "Custom shell scripts using lattice radiant"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint5",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define MOJO 1
|
|
$$MOJO=1
|
|
$$HARDWARE = 1
|
|
$$NUM_LEDS = 8
|
|
$$NUM_BTNS = 1
|
|
$$color_depth = 6
|
|
$$color_max = 63
|
|
|
|
module top(
|
|
input rst_n,
|
|
input cclk,
|
|
output [7:0] leds,
|
|
output spi_miso,
|
|
input spi_ss,
|
|
input spi_mosi,
|
|
input spi_sck,
|
|
output [3:0] spi_channel,
|
|
input avr_tx,
|
|
output avr_rx,
|
|
input avr_rx_busy,
|
|
// SDRAM
|
|
output sdram_clk,
|
|
output sdram_cle,
|
|
output sdram_dqm,
|
|
output sdram_cs,
|
|
output sdram_we,
|
|
output sdram_cas,
|
|
output sdram_ras,
|
|
output [1:0] sdram_ba,
|
|
output [12:0] sdram_a,
|
|
inout [7:0] sdram_dq,
|
|
// HDMI
|
|
output [3:0] gpdi_dp,
|
|
output [3:0] gpdi_dn,
|
|
input clk
|
|
);
|
|
|
|
wire [7:0] __main_out_leds;
|
|
|
|
wire __main_spi_miso;
|
|
wire __main_out_avr_rx;
|
|
wire [3:0] __main_out_spi_channel;
|
|
|
|
wire __main_out_sdram_clk;
|
|
wire __main_out_sdram_cle;
|
|
wire __main_out_sdram_dqm;
|
|
wire __main_out_sdram_cs;
|
|
wire __main_out_sdram_we;
|
|
wire __main_out_sdram_cas;
|
|
wire __main_out_sdram_ras;
|
|
wire [1:0] __main_out_sdram_ba;
|
|
wire [12:0] __main_out_sdram_a;
|
|
wire [3:0] __main_out_hdmi1_tmds;
|
|
wire [3:0] __main_out_hdmi1_tmdsb;
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
|
|
M_main __main(
|
|
.reset(~rst_n),
|
|
.in_run(run_main),
|
|
.out_leds(__main_out_leds),
|
|
`ifdef SDRAM
|
|
.inout_sdram_dq(sdram_dq),
|
|
.out_sdram_clk(__main_out_sdram_clk),
|
|
.out_sdram_cle(__main_out_sdram_cle),
|
|
.out_sdram_dqm(__main_out_sdram_dqm),
|
|
.out_sdram_cs(__main_out_sdram_cs),
|
|
.out_sdram_we(__main_out_sdram_we),
|
|
.out_sdram_cas(__main_out_sdram_cas),
|
|
.out_sdram_ras(__main_out_sdram_ras),
|
|
.out_sdram_ba(__main_out_sdram_ba),
|
|
.out_sdram_a(__main_out_sdram_a),
|
|
`endif
|
|
`ifdef HDMI
|
|
.out_gpdi_dp (__main_out_gpdi_dp),
|
|
.out_gpdi_dn (__main_out_gpdi_dn),
|
|
`endif
|
|
.clock(clk)
|
|
);
|
|
|
|
assign spi_miso = 1'bz;
|
|
assign avr_rx = 1'bz;
|
|
assign spi_channel = 4'bzzzz;
|
|
|
|
assign leds = __main_out_leds;
|
|
|
|
`ifdef SDRAM
|
|
assign sdram_clk = __main_out_sdram_clk;
|
|
assign sdram_cle = __main_out_sdram_cle;
|
|
assign sdram_dqm = __main_out_sdram_dqm;
|
|
assign sdram_cs = __main_out_sdram_cs;
|
|
assign sdram_we = __main_out_sdram_we;
|
|
assign sdram_cas = __main_out_sdram_cas;
|
|
assign sdram_ras = __main_out_sdram_ras;
|
|
assign sdram_ba = __main_out_sdram_ba;
|
|
assign sdram_a = __main_out_sdram_a;
|
|
`else
|
|
assign sdram_clk = 1'bz;
|
|
assign sdram_cle = 1'bz;
|
|
assign sdram_dqm = 1'bz;
|
|
assign sdram_cs = 1'bz;
|
|
assign sdram_we = 1'bz;
|
|
assign sdram_cas = 1'bz;
|
|
assign sdram_ras = 1'bz;
|
|
assign sdram_ba = 2'bzz;
|
|
assign sdram_a = 12'bzzzzzzzzzzzz;
|
|
`endif
|
|
|
|
`ifdef HDMI
|
|
assign gpdi_dp = __main_out_gpdi_dp;
|
|
assign gpdi_dn = __main_out_gpdi_dn;
|
|
`else
|
|
assign gpdi_dp = 4'bzzzz;
|
|
assign gpdi_dn = 4'bzzzz;
|
|
`endif
|
|
|
|
endmodule
|
|
NET "clk" TNM_NET = clk;
|
|
TIMESPEC TS_clk = PERIOD "clk" 50 MHz HIGH 50%;
|
|
|
|
NET "clk" LOC = P56 | IOSTANDARD = LVTTL;
|
|
NET "rst_n" LOC = P38 | IOSTANDARD = LVTTL;
|
|
|
|
NET "cclk" LOC = P70 | IOSTANDARD = LVTTL;
|
|
|
|
NET "leds<0>" LOC = P134 | IOSTANDARD = LVTTL;
|
|
NET "leds<1>" LOC = P133 | IOSTANDARD = LVTTL;
|
|
NET "leds<2>" LOC = P132 | IOSTANDARD = LVTTL;
|
|
NET "leds<3>" LOC = P131 | IOSTANDARD = LVTTL;
|
|
NET "leds<4>" LOC = P127 | IOSTANDARD = LVTTL;
|
|
NET "leds<5>" LOC = P126 | IOSTANDARD = LVTTL;
|
|
NET "leds<6>" LOC = P124 | IOSTANDARD = LVTTL;
|
|
NET "leds<7>" LOC = P123 | IOSTANDARD = LVTTL;
|
|
|
|
NET "spi_mosi" LOC = P44 | IOSTANDARD = LVTTL;
|
|
NET "spi_miso" LOC = P45 | IOSTANDARD = LVTTL;
|
|
NET "spi_ss" LOC = P48 | IOSTANDARD = LVTTL;
|
|
NET "spi_sck" LOC = P43 | IOSTANDARD = LVTTL;
|
|
NET "spi_channel<0>" LOC = P46 | IOSTANDARD = LVTTL;
|
|
NET "spi_channel<1>" LOC = P61 | IOSTANDARD = LVTTL;
|
|
NET "spi_channel<2>" LOC = P62 | IOSTANDARD = LVTTL;
|
|
NET "spi_channel<3>" LOC = P65 | IOSTANDARD = LVTTL;
|
|
|
|
NET "avr_tx" LOC = P55 | IOSTANDARD = LVTTL;
|
|
NET "avr_rx" LOC = P59 | IOSTANDARD = LVTTL;
|
|
NET "avr_rx_busy" LOC = P39 | IOSTANDARD = LVTTL;
|
|
|
|
NET "sdram_clk" LOC = P29 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_cle" LOC = P30 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dqm" LOC = P74 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_cs" LOC = P84 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_we" LOC = P81 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_cas" LOC = P82 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_ras" LOC = P83 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
|
|
NET "sdram_ba<0>" LOC = P85 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_ba<1>" LOC = P87 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
|
|
NET "sdram_a<0>" LOC = P101 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<1>" LOC = P102 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<2>" LOC = P104 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<3>" LOC = P105 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<4>" LOC = P5 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<5>" LOC = P6 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<6>" LOC = P7 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<7>" LOC = P8 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<8>" LOC = P9 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<9>" LOC = P10 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<10>" LOC = P88 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<11>" LOC = P27 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_a<12>" LOC = P26 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
|
|
NET "sdram_dq<0>" LOC = P75 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<1>" LOC = P78 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<2>" LOC = P79 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<3>" LOC = P80 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<4>" LOC = P34 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<5>" LOC = P35 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<6>" LOC = P40 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
NET "sdram_dq<7>" LOC = P41 | IOSTANDARD = LVTTL | SLEW = FAST;
|
|
|
|
NET "gpdi_dp(3)" LOC = "P144" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ; # Clock
|
|
NET "gpdi_dn(3)" LOC = "P143" |IOSTANDARD = TMDS_33 | CLOCK_DEDICATED_ROUTE = FALSE ;
|
|
NET "gpdi_dp(2)" LOC = "P138" |IOSTANDARD = TMDS_33 ; # Red
|
|
NET "gpdi_dn(2)" LOC = "P137" |IOSTANDARD = TMDS_33 ;
|
|
NET "gpdi_dp(1)" LOC = "P140" |IOSTANDARD = TMDS_33 ; # Green
|
|
NET "gpdi_dn(1)" LOC = "P139" |IOSTANDARD = TMDS_33 ;
|
|
NET "gpdi_dp(0)" LOC = "P142" |IOSTANDARD = TMDS_33 ; # Blue
|
|
NET "gpdi_dn(0)" LOC = "P141" |IOSTANDARD = TMDS_33 ;
|
|
{
|
|
"name": "mojov3",
|
|
"variants": [
|
|
{
|
|
"name": "configurable",
|
|
"framework" : "mojov3.v",
|
|
"pins": [
|
|
{"set" : "basic"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "edalize",
|
|
"description": "Build using Edalize",
|
|
"tool": "ise",
|
|
"tool_options": [
|
|
{
|
|
"family": "spartan6",
|
|
"device": "xc6slx9",
|
|
"package": "tqg144",
|
|
"speed" : -2
|
|
}
|
|
],
|
|
"toplevel" : "top",
|
|
"bitstream" : "top.bin",
|
|
"constraints": [
|
|
{"name": "mojov3.ucf", "file_type": "UCF"}
|
|
],
|
|
"program": [
|
|
{"cmd" : "promgen", "args" : "-u 0 top.bit -p bin -spi -w"},
|
|
{"cmd" : "printf", "args" : "\"\\n\\nThe programming file has been generated in BUILD_mojov3/top.bin, please use Mojo Loader to program your board\\n\\n\""},
|
|
{"cmd" : "mojo-loader", "args" : "-b top.bin"}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io" : "output"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
`define ICARUS 1
|
|
$$ICARUS = 1
|
|
$$SIMULATION = 1
|
|
$$NUM_LEDS = 8
|
|
$$color_depth = 6
|
|
$$color_max = 63
|
|
$$config['bram_wenable_width'] = 'data'
|
|
$$config['dualport_bram_wenable0_width'] = 'data'
|
|
$$config['dualport_bram_wenable1_width'] = 'data'
|
|
|
|
`timescale 1ns / 1ps
|
|
|
|
module top;
|
|
|
|
reg clk;
|
|
reg rst_n;
|
|
|
|
wire [7:0] __main_leds;
|
|
|
|
`ifdef VGA
|
|
wire __main_video_clock;
|
|
wire __main_video_hs;
|
|
wire __main_video_vs;
|
|
wire [5:0] __main_video_r;
|
|
wire [5:0] __main_video_g;
|
|
wire [5:0] __main_video_b;
|
|
`endif
|
|
|
|
`ifdef UART
|
|
wire __main_uart_tx;
|
|
wire __main_uart_rx = 0;
|
|
`endif
|
|
|
|
`ifdef HDMI
|
|
wire [3:0] __main_out_gpdi_dp;
|
|
wire [3:0] __main_out_gpdi_dn;
|
|
`endif
|
|
|
|
initial begin
|
|
clk = 1'b0;
|
|
rst_n = 1'b0;
|
|
$display("icarus framework started");
|
|
$dumpfile("icarus.fst");
|
|
`ifdef DUMP_TOP_ONLY
|
|
$dumpvars(1,top); // dump only top (faster and smaller)
|
|
`else
|
|
$dumpvars(0,top); // dump all (for full debugging)
|
|
`endif
|
|
`ifdef CLOCK_25MHz
|
|
// generate a 25 MHz clock
|
|
repeat(4) #20 clk = ~clk;
|
|
rst_n = 1'b1;
|
|
forever #20 clk = ~clk;
|
|
`else
|
|
// generate a 100 MHz clock
|
|
repeat(4) #5 clk = ~clk;
|
|
rst_n = 1'b1;
|
|
forever #5 clk = ~clk;
|
|
`endif
|
|
end
|
|
|
|
reg ready = 0;
|
|
reg [3:0] RST_d;
|
|
reg [3:0] RST_q;
|
|
|
|
always @* begin
|
|
RST_d = RST_q >> 1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (ready) begin
|
|
RST_q <= RST_d;
|
|
end else begin
|
|
ready <= 1;
|
|
RST_q <= 4'b1111;
|
|
end
|
|
end
|
|
|
|
wire run_main;
|
|
assign run_main = 1'b1;
|
|
wire done_main;
|
|
|
|
M_main __main(
|
|
.clock(clk),
|
|
.reset(RST_d[0]),
|
|
.out_leds(__main_leds),
|
|
`ifdef VGA
|
|
.out_video_clock(__main_video_clock),
|
|
.out_video_r(__main_video_r),
|
|
.out_video_g(__main_video_g),
|
|
.out_video_b(__main_video_b),
|
|
.out_video_hs(__main_video_hs),
|
|
.out_video_vs(__main_video_vs),
|
|
`endif
|
|
`ifdef UART
|
|
.out_uart_tx(__main_uart_tx),
|
|
.in_uart_rx(__main_uart_rx),
|
|
`endif
|
|
`ifdef HDMI
|
|
.out_gpdi_dp (__main_out_gpdi_dp),
|
|
.out_gpdi_dn (__main_out_gpdi_dn),
|
|
`endif
|
|
.in_run(run_main),
|
|
.out_done(done_main)
|
|
);
|
|
|
|
always @* begin
|
|
if (done_main && !RST_d[0]) $finish;
|
|
end
|
|
|
|
endmodule
|
|
|
|
#!/bin/bash
|
|
|
|
case "$(uname -s)" in
|
|
MINGW*|CYGWIN*)
|
|
SILICE_DIR=`cygpath $SILICE_DIR`
|
|
BUILD_DIR=`cygpath $BUILD_DIR`
|
|
FRAMEWORKS_DIR=`cygpath $FRAMEWORKS_DIR`
|
|
FRAMEWORK_FILE=`cygpath $FRAMEWORK_FILE`
|
|
BOARD_DIR=`cygpath $BOARD_DIR`
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
echo "build script: SILICE_DIR = $SILICE_DIR"
|
|
echo "build script: BUILD_DIR = $BUILD_DIR"
|
|
echo "build script: BOARD_DIR = $BOARD_DIR"
|
|
echo "build script: FRAMEWORKS_DIR = $FRAMEWORKS_DIR"
|
|
echo "build script: FRAMEWORK_FILE = $FRAMEWORK_FILE"
|
|
|
|
export PATH=$PATH:$SILICE_DIR:$SILICE_DIR/../tools/fpga-binutils/mingw64/bin/
|
|
case "$(uname -s)" in
|
|
MINGW*)
|
|
export PYTHONHOME=/mingw64/bin
|
|
export PYTHONPATH=/mingw64/lib/python3.8/
|
|
export QT_QPA_PLATFORM_PLUGIN_PATH=/mingw64/share/qt5/plugins
|
|
;;
|
|
*)
|
|
esac
|
|
|
|
cd $BUILD_DIR
|
|
|
|
rm build* icarus.fst icarus.fst.hier
|
|
|
|
silice --frameworks_dir $FRAMEWORKS_DIR -f $FRAMEWORK_FILE -o build.v $1 "${@:2}"
|
|
|
|
iverilog -o build build.v
|
|
vvp build -fst
|
|
|
|
gtkwave icarus.fst
|
|
{
|
|
"name": "icarus",
|
|
"variants": [
|
|
{
|
|
"name" : "configurable",
|
|
"framework" : "icarus.v",
|
|
"pins" : [
|
|
{"set" : "basic"},
|
|
{"set" : "vga", "define" : "VGA=1"},
|
|
{"set" : "hdmi", "define" : "HDMI=1"},
|
|
{"set" : "uart", "define" : "UART=1"},
|
|
{"set" : "top_only", "define" : "DUMP_TOP_ONLY=1"}
|
|
],
|
|
"builders": [
|
|
{
|
|
"builder" : "shell",
|
|
"command" : "icarus.sh",
|
|
"description": "Simulates with icarus and opens gtkwave for visualization"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"pins": {
|
|
"basic": [
|
|
{
|
|
"name": "leds",
|
|
"type": "uint8",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"uart": [
|
|
{
|
|
"name": "uart_tx",
|
|
"type": "uint1",
|
|
"io" : "output"
|
|
},
|
|
{
|
|
"name": "uart_rx",
|
|
"type": "uint1",
|
|
"io" : "input"
|
|
}
|
|
],
|
|
"vga": [
|
|
{
|
|
"name": "vga_hs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_vs",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_r",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_g",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "vga_b",
|
|
"type": "uint6",
|
|
"io": "output"
|
|
}
|
|
],
|
|
"hdmi": [
|
|
{
|
|
"name": "gpdi_dq",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
},
|
|
{
|
|
"name": "gpdi_dn",
|
|
"type": "uint1",
|
|
"io": "output"
|
|
}
|
|
]
|
|
}
|
|
}
|