Created
November 10, 2013 20:09
-
-
Save madmo/7403249 to your computer and use it in GitHub Desktop.
Minimal nand controller ip core in myhdl (untested)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from myhdl import * | |
FPGA_NAND_CMD_MASK = (0x7 << 28) | |
FPGA_NAND_CMD_COMMAND = (0x0 << 28) | |
FPGA_NAND_CMD_ADDR = (0x1 << 28) | |
FPGA_NAND_CMD_READ = (0x2 << 28) | |
FPGA_NAND_CMD_WRITE = (0x3 << 28) | |
FPGA_NAND_BUSY = (0x1 << 15) | |
FPGA_NAND_ENABLE = (0x1 << 31) | |
FPGA_NAND_DATA_SHIFT = 16 | |
def gen_ce(address_i, lowaddr, addrlen=None, highaddr=None): | |
if lowaddr < 0: | |
raise AttributeError("lowaddr can't be lower than zero") | |
if addrlen == None and highaddr == None: | |
highaddr = lowaddr + 1 | |
if highaddr == None: | |
highaddr = lowaddr + addrlen | |
if lowaddr >= highaddr: | |
raise AttributeError("wrong addr range") | |
sig = Signal(bool(0)) | |
@always_comb | |
def ce_logic(): | |
if address_i >= lowaddr and address_i < highaddr: | |
sig.next = True | |
else: | |
sig.next = False | |
return (sig, ce_logic) | |
def gen_nand_interface( | |
# avalon interface | |
membase, | |
address_i, | |
readdata_o, | |
writedata_i, | |
clk_i, | |
reset_i, | |
read_i, | |
write_i, | |
# flash interface | |
data_io, | |
ale_o, | |
ce_n_o, | |
cle_o, | |
re_n_o, | |
we_n_o, | |
rb_i): | |
ce, ce_gen = gen_ce(address_i, membase) | |
@always(clk_i.posedge) | |
def reset(): | |
if reset_i: | |
readdata_o = 0 | |
data_io = 0 | |
ale_o = 0 | |
ce_n_o = 1 | |
cle_o = 0 | |
re_n_o = 0 | |
we_n_o = 0 | |
wp_n_o = 0 | |
@always(clk_i.posedge) | |
def write_logic(): | |
if ce and write_i and not read_i: | |
data_io.next = (writedata_i >> FPGA_NAND_DATA_SHIFT) & 0xff | |
if writedata_i & FPGA_NAND_ENABLE: | |
ce_n_o.next = 0 | |
else: | |
ce_n_o.next = 1 | |
if writedata_i & FPGA_NAND_CMD_ADDR: | |
ale_o.next = 1 | |
else: | |
ale_o.next = 0 | |
if writedata_i & FPGA_NAND_CMD_COMMAND: | |
cle_o.next = 1 | |
else: | |
cle_o.next = 0 | |
if writedata_i & FPGA_NAND_CMD_WRITE: | |
we_n_o.next = 0 | |
else: | |
we_n_o.next = 1 | |
if writedata_i & FPGA_NAND_CMD_READ: | |
re_n_o.next = 0 | |
else: | |
re_n_o.next = 1 | |
@always(clk_i.posedge) | |
def read_logic(): | |
if ce and read_i and not write_i: | |
tmp = (data_io << FPGA_NAND_DATA_SHIFT) & 0xff | |
if not rb_i: | |
tmp |= FPGA_NAND_BUSY | |
readdata_o.next = tmp | |
return reset, ce_gen, write_logic, read_logic | |
if __name__ == "__main__": | |
membase = 0x80000000 | |
address = Signal(intbv(0)[32:]) | |
readdata, writedata = [Signal(intbv(0)[32:]) for i in range(2)] | |
toVerilog(gen_nand_interface, | |
membase, | |
Signal(intbv(0)[32:]), | |
readdata, | |
writedata, | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(intbv(0)[8:]), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0)), | |
Signal(bool(0))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment