8bitworkshop/src/worker/fs/fsSilice.data

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"
}
]
}
}