support IO standards LVCMOS 33/25/18/15/12, LVTTL

This commit is contained in:
Wolfgang Spraul 2012-10-03 15:19:59 +02:00
parent d96fb235ee
commit a356ac5b55
11 changed files with 481 additions and 143 deletions

14
LINKS
View File

@ -4,3 +4,17 @@ http://en.wikipedia.org/wiki/Wikipedia:WikiProject_Electronics/Programs
http://qfsm.sourceforge.net/about.html
http://www.texample.net/tikz/examples/timing-diagram/
http://smithsonianchips.si.edu/ice/s4.htm
http://www.hottconsultants.com/techtips/pcb-stack-up-3.html
Andrew's redtin logic analyzer
http://code.google.com/p/red-tin-logic-analyzer
gtkwave wave viewer
http://gtkwave.sourceforge.net
Fedora Electronic Lab tool overview
http://spins.fedoraproject.org/fel/#portfolio
http://chitlesh.fedorapeople.org/FEL/list.html
with links to magic, toped, qucs, iverilog, alliance, etc.

1
README
View File

@ -61,6 +61,7 @@ TODO
short-term (1 month):
* add lut_encoding autotest for lut6 and lut5 in a-d position
of x(m), x(l), l and m devs
* more cases in logic_cfg test
* example: blinking_led
* example: counter (including clock, jtag)
* support reading iologic switches

View File

@ -514,7 +514,7 @@ int test_routing_sw_from_iob(struct test_state* tstate,
rc = fpga_find_iob(tstate->model, "P48", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
iob_dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
if (!iob_dev) FAIL(EINVAL);
@ -851,7 +851,7 @@ static int test_iologic_switches(struct test_state* tstate)
// input IOB
rc = fpga_find_iob(tstate->model, iob_name, &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
rc = test_iologic_switches2(tstate, iob_y, iob_x, iob_type_idx);
if (rc) FAIL(rc);
@ -860,7 +860,7 @@ static int test_iologic_switches(struct test_state* tstate)
// output IOB
rc = fpga_find_iob(tstate->model, iob_name, &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
rc = test_iologic_switches2(tstate, iob_y, iob_x, iob_type_idx);
if (rc) FAIL(rc);
@ -873,16 +873,17 @@ fail:
static int test_iob_config(struct test_state* tstate)
{
int iob_y, iob_x, iob_type_idx, rc;
int iob_y, iob_x, iob_type_idx, i, j, rc;
net_idx_t net_idx;
struct fpga_device* dev;
int drive_strengths[] = {2, 4, 6, 8, 12, 16, 24};
tstate->diff_to_null = 1;
// P45 is an IOBS
rc = fpga_find_iob(tstate->model, "P45", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
if (!dev) FAIL(EINVAL);
@ -896,7 +897,7 @@ static int test_iob_config(struct test_state* tstate)
// P46 is an IOBM
rc = fpga_find_iob(tstate->model, "P46", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
if ((rc = diff_printf(tstate))) FAIL(rc);
fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
@ -904,7 +905,7 @@ static int test_iob_config(struct test_state* tstate)
// P47 is an IOBS
rc = fpga_find_iob(tstate->model, "P47", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
if (!dev) FAIL(EINVAL);
@ -928,20 +929,10 @@ static int test_iob_config(struct test_state* tstate)
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.suspend = SUSP_3STATE;
dev->u.iob.drive_strength = 2;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 4;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 6;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 8;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 12;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 16;
rc = diff_printf(tstate); if (rc) FAIL(rc);
dev->u.iob.drive_strength = 24;
rc = diff_printf(tstate); if (rc) FAIL(rc);
for (i = 0; i < sizeof(drive_strengths)/sizeof(*drive_strengths); i++) {
dev->u.iob.drive_strength = drive_strengths[i];
rc = diff_printf(tstate); if (rc) FAIL(rc);
}
dev->u.iob.drive_strength = 8;
dev->u.iob.slew = SLEW_SLOW;
@ -957,7 +948,7 @@ static int test_iob_config(struct test_state* tstate)
// P48 is an IOBM
rc = fpga_find_iob(tstate->model, "P48", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx, IO_LVCMOS33);
if (rc) FAIL(rc);
dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
if (!dev) FAIL(EINVAL);
@ -977,7 +968,59 @@ static int test_iob_config(struct test_state* tstate)
if (rc) FAIL(rc);
if ((rc = diff_printf(tstate))) FAIL(rc);
fnet_delete(tstate->model, net_idx);
fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
// different IO standards
// The left (3) and right (1) banks have higher voltage ranges
// than the top (0) and bottom (2) banks, so we test this on
// the left side (ug381 page 13).
// todo: IO_SSTL2_I is not implemented right
{ const char* io_std[] = { IO_LVCMOS33, IO_LVCMOS25, IO_LVCMOS18,
IO_LVCMOS18_JEDEC, IO_LVCMOS15, IO_LVCMOS15_JEDEC,
IO_LVCMOS12, IO_LVCMOS12_JEDEC, IO_LVTTL, IO_SSTL2_I, 0 };
i = 0;
while (io_std[i]) {
// input
rc = fpga_find_iob(tstate->model, "P22", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_input(tstate->model, iob_y, iob_x, iob_type_idx, io_std[i]);
if (rc) FAIL(rc);
if ((rc = diff_printf(tstate))) FAIL(rc);
fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
i++;
}
i = 0;
while (io_std[i]) {
// output
rc = fpga_find_iob(tstate->model, "P22", &iob_y, &iob_x, &iob_type_idx);
if (rc) FAIL(rc);
rc = fdev_iob_output(tstate->model, iob_y, iob_x, iob_type_idx, io_std[i]);
if (rc) FAIL(rc);
if (!strcmp(io_std[i], IO_SSTL2_I)) {
rc = diff_printf(tstate); if (rc) FAIL(rc);
} else {
dev = fdev_p(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
if (!dev) FAIL(EINVAL);
for (j = 0; j < sizeof(drive_strengths)/sizeof(*drive_strengths); j++) {
if ((!strcmp(io_std[i], IO_LVCMOS15)
|| !strcmp(io_std[i], IO_LVCMOS15_JEDEC))
&& drive_strengths[j] == 24)
continue;
if ((!strcmp(io_std[i], IO_LVCMOS12)
|| !strcmp(io_std[i], IO_LVCMOS12_JEDEC))
&& (drive_strengths[j] == 16 || drive_strengths[j] == 24))
continue;
dev->u.iob.drive_strength = drive_strengths[j];
rc = diff_printf(tstate); if (rc) FAIL(rc);
}
}
fdev_delete(tstate->model, iob_y, iob_x, DEV_IOB, iob_type_idx);
i++;
}}
return 0;
fail:
return rc;
@ -1126,7 +1169,6 @@ static int test_lut_encoding(struct test_state* tstate)
}
}
}
out:
return 0;
fail:
return rc;

View File

@ -25,17 +25,17 @@ int main(int argc, char** argv)
if ((rc = fpga_find_iob(&model, "P45", &iob_inA_y, &iob_inA_x,
&iob_inA_type_idx))) FAIL(rc);
if ((rc = fdev_iob_input(&model, iob_inA_y, iob_inA_x,
iob_inA_type_idx))) FAIL(rc);
iob_inA_type_idx, IO_LVCMOS33))) FAIL(rc);
if ((rc = fpga_find_iob(&model, "P46", &iob_inB_y, &iob_inB_x,
&iob_inB_type_idx))) FAIL(rc);
if ((rc = fdev_iob_input(&model, iob_inB_y, iob_inB_x,
iob_inB_type_idx))) FAIL(rc);
iob_inB_type_idx, IO_LVCMOS33))) FAIL(rc);
if ((rc = fpga_find_iob(&model, "P48", &iob_out_y, &iob_out_x,
&iob_out_type_idx))) FAIL(rc);
if ((rc = fdev_iob_output(&model, iob_out_y, iob_out_x,
iob_out_type_idx))) FAIL(rc);
iob_out_type_idx, IO_LVCMOS33))) FAIL(rc);
logic_y = 68;
logic_x = 13;

View File

@ -25,17 +25,17 @@ int main(int argc, char** argv)
if ((rc = fpga_find_iob(&model, "P45", &iob_inA_y, &iob_inA_x,
&iob_inA_type_idx))) FAIL(rc);
if ((rc = fdev_iob_input(&model, iob_inA_y, iob_inA_x,
iob_inA_type_idx))) FAIL(rc);
iob_inA_type_idx, IO_LVCMOS33))) FAIL(rc);
if ((rc = fpga_find_iob(&model, "P46", &iob_inB_y, &iob_inB_x,
&iob_inB_type_idx))) FAIL(rc);
if ((rc = fdev_iob_input(&model, iob_inB_y, iob_inB_x,
iob_inB_type_idx))) FAIL(rc);
iob_inB_type_idx, IO_LVCMOS33))) FAIL(rc);
if ((rc = fpga_find_iob(&model, "P48", &iob_out_y, &iob_out_x,
&iob_out_type_idx))) FAIL(rc);
if ((rc = fdev_iob_output(&model, iob_out_y, iob_out_x,
iob_out_type_idx))) FAIL(rc);
iob_out_type_idx, IO_LVCMOS33))) FAIL(rc);
logic_y = 68;
logic_x = 13;

View File

@ -123,17 +123,30 @@ static int write_iobs(struct fpga_bits* bits, struct fpga_model* model)
if (dev->u.iob.istandard[0]) {
if (!dev->u.iob.I_mux
|| !dev->u.iob.bypass_mux
|| strcmp(dev->u.iob.istandard, IO_LVCMOS33)
|| dev->u.iob.ostandard[0])
HERE();
u64 = XC6_IOB_INSTANTIATED;
u64 |= XC6_IOB_INPUT_LVCMOS33;
if (dev->u.iob.I_mux == IMUX_I)
u64 |= XC6_IOB_IMUX_I;
else if (dev->u.iob.I_mux == IMUX_I_B)
u64 = XC6_IOB_INPUT | XC6_IOB_INSTANTIATED;
if (dev->u.iob.I_mux == IMUX_I_B)
u64 |= XC6_IOB_IMUX_I_B;
else HERE();
if (!strcmp(dev->u.iob.istandard, IO_LVCMOS33)
|| !strcmp(dev->u.iob.istandard, IO_LVCMOS25)
|| !strcmp(dev->u.iob.istandard, IO_LVTTL))
u64 |= XC6_IOB_INPUT_LVCMOS33_25_LVTTL;
else if (!strcmp(dev->u.iob.istandard, IO_LVCMOS18)
|| !strcmp(dev->u.iob.istandard, IO_LVCMOS15)
|| !strcmp(dev->u.iob.istandard, IO_LVCMOS12))
u64 |= XC6_IOB_INPUT_LVCMOS18_15_12;
else if (!strcmp(dev->u.iob.istandard, IO_LVCMOS18_JEDEC)
|| !strcmp(dev->u.iob.istandard, IO_LVCMOS15_JEDEC)
|| !strcmp(dev->u.iob.istandard, IO_LVCMOS12_JEDEC))
u64 |= XC6_IOB_INPUT_LVCMOS18_15_12_JEDEC;
else if (!strcmp(dev->u.iob.istandard, IO_SSTL2_I))
u64 |= XC6_IOB_INPUT_SSTL2_I;
else
HERE();
frame_set_u64(&bits->d[IOB_DATA_START
+ part_idx*IOB_ENTRY_LEN], u64);
@ -141,29 +154,85 @@ static int write_iobs(struct fpga_bits* bits, struct fpga_model* model)
if (!dev->u.iob.drive_strength
|| !dev->u.iob.slew
|| !dev->u.iob.suspend
|| strcmp(dev->u.iob.ostandard, IO_LVCMOS33)
|| dev->u.iob.istandard[0])
HERE();
u64 = XC6_IOB_INSTANTIATED;
// for now we always turn on O_PINW even if no net
// is connected to the pinw
u64 |= XC6_IOB_MASK_O_PINW;
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16; break;
case 24: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24; break;
default: HERE();
}
u64 |= XC6_IOB_O_PINW;
if (!strcmp(dev->u.iob.ostandard, IO_LVTTL)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_16; break;
case 24: u64 |= XC6_IOB_OUTPUT_LVTTL_DRIVE_24; break;
default: FAIL(EINVAL);
}
} else if (!strcmp(dev->u.iob.ostandard, IO_LVCMOS33)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS33_25_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16; break;
case 24: u64 |= XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24; break;
default: FAIL(EINVAL);
}
} else if (!strcmp(dev->u.iob.ostandard, IO_LVCMOS25)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS33_25_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_16; break;
case 24: u64 |= XC6_IOB_OUTPUT_LVCMOS25_DRIVE_24; break;
default: FAIL(EINVAL);
}
} else if (!strcmp(dev->u.iob.ostandard, IO_LVCMOS18)
|| !strcmp(dev->u.iob.ostandard, IO_LVCMOS18_JEDEC)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_16; break;
case 24: u64 |= XC6_IOB_OUTPUT_LVCMOS18_DRIVE_24; break;
default: FAIL(EINVAL);
}
} else if (!strcmp(dev->u.iob.ostandard, IO_LVCMOS15)
|| !strcmp(dev->u.iob.ostandard, IO_LVCMOS15_JEDEC)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_12; break;
case 16: u64 |= XC6_IOB_OUTPUT_LVCMOS15_DRIVE_16; break;
default: FAIL(EINVAL);
}
} else if (!strcmp(dev->u.iob.ostandard, IO_LVCMOS12)
|| !strcmp(dev->u.iob.ostandard, IO_LVCMOS12_JEDEC)) {
switch (dev->u.iob.drive_strength) {
case 2: u64 |= XC6_IOB_OUTPUT_LVCMOS12_DRIVE_2; break;
case 4: u64 |= XC6_IOB_OUTPUT_LVCMOS12_DRIVE_4; break;
case 6: u64 |= XC6_IOB_OUTPUT_LVCMOS12_DRIVE_6; break;
case 8: u64 |= XC6_IOB_OUTPUT_LVCMOS12_DRIVE_8; break;
case 12: u64 |= XC6_IOB_OUTPUT_LVCMOS12_DRIVE_12; break;
default: FAIL(EINVAL);
}
} else FAIL(EINVAL);
switch (dev->u.iob.slew) {
case SLEW_SLOW: u64 |= XC6_IOB_SLEW_SLOW; break;
case SLEW_FAST: u64 |= XC6_IOB_SLEW_FAST; break;
case SLEW_QUIETIO: u64 |= XC6_IOB_SLEW_QUIETIO; break;
default: HERE();
default: FAIL(EINVAL);
}
switch (dev->u.iob.suspend) {
case SUSP_LAST_VAL: u64 |= XC6_IOB_SUSP_LAST_VAL; break;
@ -172,7 +241,7 @@ static int write_iobs(struct fpga_bits* bits, struct fpga_model* model)
case SUSP_3STATE_PULLDOWN: u64 |= XC6_IOB_SUSP_3STATE_PULLDOWN; break;
case SUSP_3STATE_KEEPER: u64 |= XC6_IOB_SUSP_3STATE_KEEPER; break;
case SUSP_3STATE_OCT_ON: u64 |= XC6_IOB_SUSP_3STATE_OCT_ON; break;
default: HERE();
default: FAIL(EINVAL);
}
frame_set_u64(&bits->d[IOB_DATA_START
@ -219,58 +288,214 @@ static int extract_iobs(struct fpga_model* model, struct fpga_bits* bits)
clear_bit(bits, /*row*/ 0, get_rightside_major(XC6SLX9),
/*minor*/ 22, 64*15+XC6_HCLK_BITS+4);
}
if ((u64 & XC6_IOB_MASK_INSTANTIATED) == XC6_IOB_INSTANTIATED)
u64 &= ~XC6_IOB_MASK_INSTANTIATED;
if (u64 & XC6_IOB_INSTANTIATED)
u64 &= ~XC6_IOB_INSTANTIATED;
else
HERE();
switch (u64 & XC6_IOB_MASK_IO) {
case XC6_IOB_INPUT_LVCMOS33:
u64 &= ~XC6_IOB_MASK_IO;
strcpy(cfg.istandard, IO_LVCMOS33);
case XC6_IOB_INPUT:
cfg.bypass_mux = BYPASS_MUX_I;
switch (u64 & XC6_IOB_MASK_I_MUX) {
case XC6_IOB_IMUX_I:
u64 &= ~XC6_IOB_MASK_I_MUX;
cfg.I_mux = IMUX_I;
if (u64 & XC6_IOB_IMUX_I_B) {
cfg.I_mux = IMUX_I_B;
u64 &= ~XC6_IOB_IMUX_I_B;
} else
cfg.I_mux = IMUX_I;
switch (u64 & XC6_IOB_MASK_IN_TYPE) {
case XC6_IOB_INPUT_LVCMOS33_25_LVTTL:
u64 &= ~XC6_IOB_MASK_IN_TYPE;
strcpy(cfg.istandard, IO_LVCMOS25);
break;
case XC6_IOB_IMUX_I_B:
u64 &= ~XC6_IOB_MASK_I_MUX;
cfg.I_mux = IMUX_I_B;
case XC6_IOB_INPUT_LVCMOS18_15_12:
u64 &= ~XC6_IOB_MASK_IN_TYPE;
strcpy(cfg.istandard, IO_LVCMOS12);
break;
case XC6_IOB_INPUT_LVCMOS18_15_12_JEDEC:
u64 &= ~XC6_IOB_MASK_IN_TYPE;
strcpy(cfg.istandard, IO_LVCMOS12_JEDEC);
break;
case XC6_IOB_INPUT_SSTL2_I:
u64 &= ~XC6_IOB_MASK_IN_TYPE;
strcpy(cfg.istandard, IO_SSTL2_I);
break;
default: HERE();
}
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16:
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24:
switch (u64 & XC6_IOB_MASK_IO) {
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2:
cfg.drive_strength = 2; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4:
cfg.drive_strength = 4; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6:
cfg.drive_strength = 6; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8:
cfg.drive_strength = 8; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12:
cfg.drive_strength = 12; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16:
cfg.drive_strength = 16; break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24:
cfg.drive_strength = 24; break;
default: HERE(); break;
}
u64 &= ~XC6_IOB_MASK_IO;
u64 &= ~XC6_IOB_MASK_O_PINW;
break;
case XC6_IOB_OUTPUT_LVCMOS33_25_DRIVE_2:
cfg.drive_strength = 2;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVCMOS33);
cfg.O_used = 1;
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVCMOS33);
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVCMOS33);
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVCMOS33);
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16:
cfg.drive_strength = 16;
strcpy(cfg.ostandard, IO_LVCMOS33);
break;
case XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24:
cfg.drive_strength = 24;
strcpy(cfg.ostandard, IO_LVCMOS33);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_16:
cfg.drive_strength = 16;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVCMOS25_DRIVE_24:
cfg.drive_strength = 24;
strcpy(cfg.ostandard, IO_LVCMOS25);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_2:
cfg.drive_strength = 2;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_16:
cfg.drive_strength = 16;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVTTL_DRIVE_24:
cfg.drive_strength = 24;
strcpy(cfg.ostandard, IO_LVTTL);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_2:
cfg.drive_strength = 2;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_16:
cfg.drive_strength = 16;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS18_DRIVE_24:
cfg.drive_strength = 24;
strcpy(cfg.ostandard, IO_LVCMOS18);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_2:
cfg.drive_strength = 2;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS15_DRIVE_16:
cfg.drive_strength = 16;
strcpy(cfg.ostandard, IO_LVCMOS15);
break;
case XC6_IOB_OUTPUT_LVCMOS12_DRIVE_2:
cfg.drive_strength = 2;
strcpy(cfg.ostandard, IO_LVCMOS12);
break;
case XC6_IOB_OUTPUT_LVCMOS12_DRIVE_4:
cfg.drive_strength = 4;
strcpy(cfg.ostandard, IO_LVCMOS12);
break;
case XC6_IOB_OUTPUT_LVCMOS12_DRIVE_6:
cfg.drive_strength = 6;
strcpy(cfg.ostandard, IO_LVCMOS12);
break;
case XC6_IOB_OUTPUT_LVCMOS12_DRIVE_8:
cfg.drive_strength = 8;
strcpy(cfg.ostandard, IO_LVCMOS12);
break;
case XC6_IOB_OUTPUT_LVCMOS12_DRIVE_12:
cfg.drive_strength = 12;
strcpy(cfg.ostandard, IO_LVCMOS12);
break;
default: HERE(); break;
}
if (cfg.istandard[0] || cfg.ostandard[0])
u64 &= ~XC6_IOB_MASK_IO;
if (cfg.ostandard[0]) {
cfg.O_used = 1;
u64 &= ~XC6_IOB_O_PINW;
if (!strcmp(cfg.ostandard, IO_LVCMOS12)
|| !strcmp(cfg.ostandard, IO_LVCMOS15)
|| !strcmp(cfg.ostandard, IO_LVCMOS18)
|| !strcmp(cfg.ostandard, IO_LVCMOS25)
|| !strcmp(cfg.ostandard, IO_LVCMOS33)
|| !strcmp(cfg.ostandard, IO_LVTTL)) {
switch (u64 & XC6_IOB_MASK_SLEW) {
case XC6_IOB_SLEW_SLOW:
u64 &= ~XC6_IOB_MASK_SLEW;
@ -286,35 +511,34 @@ static int extract_iobs(struct fpga_model* model, struct fpga_bits* bits)
break;
default: HERE();
}
switch (u64 & XC6_IOB_MASK_SUSPEND) {
case XC6_IOB_SUSP_3STATE:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE;
break;
case XC6_IOB_SUSP_3STATE_OCT_ON:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_OCT_ON;
break;
case XC6_IOB_SUSP_3STATE_KEEPER:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_KEEPER;
break;
case XC6_IOB_SUSP_3STATE_PULLUP:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_PULLUP;
break;
case XC6_IOB_SUSP_3STATE_PULLDOWN:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_PULLDOWN;
break;
case XC6_IOB_SUSP_LAST_VAL:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_LAST_VAL;
break;
default: HERE();
}
break;
default: HERE(); break;
}
switch (u64 & XC6_IOB_MASK_SUSPEND) {
case XC6_IOB_SUSP_3STATE:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE;
break;
case XC6_IOB_SUSP_3STATE_OCT_ON:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_OCT_ON;
break;
case XC6_IOB_SUSP_3STATE_KEEPER:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_KEEPER;
break;
case XC6_IOB_SUSP_3STATE_PULLUP:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_PULLUP;
break;
case XC6_IOB_SUSP_3STATE_PULLDOWN:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_3STATE_PULLDOWN;
break;
case XC6_IOB_SUSP_LAST_VAL:
u64 &= ~XC6_IOB_MASK_SUSPEND;
cfg.suspend = SUSP_LAST_VAL;
break;
default: HERE();
}
}
if (!u64) {
frame_set_u64(&bits->d[IOB_DATA_START

View File

@ -682,7 +682,8 @@ fail:
// iob device
//
int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx)
int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx,
const char* io_std)
{
struct fpga_device* dev;
int rc;
@ -692,7 +693,7 @@ int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx)
rc = reset_required_pins(dev);
if (rc) FAIL(rc);
strcpy(dev->u.iob.istandard, IO_LVCMOS33);
strcpy(dev->u.iob.istandard, io_std);
dev->u.iob.bypass_mux = BYPASS_MUX_I;
dev->u.iob.I_mux = IMUX_I;
dev->instantiated = 1;
@ -701,7 +702,8 @@ fail:
return rc;
}
int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx)
int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx,
const char* io_std)
{
struct fpga_device* dev;
int rc;
@ -711,11 +713,21 @@ int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx)
rc = reset_required_pins(dev);
if (rc) FAIL(rc);
strcpy(dev->u.iob.ostandard, IO_LVCMOS33);
dev->u.iob.drive_strength = 8;
strcpy(dev->u.iob.ostandard, io_std);
dev->u.iob.O_used = 1;
dev->u.iob.slew = SLEW_QUIETIO;
dev->u.iob.suspend = SUSP_3STATE;
if (strcmp(io_std, IO_SSTL2_I)) {
// also see ug381 page 31
if (!strcmp(io_std, IO_LVCMOS33)
|| !strcmp(io_std, IO_LVCMOS25))
dev->u.iob.drive_strength = 12;
else if (!strcmp(io_std, IO_LVCMOS12)
|| !strcmp(io_std, IO_LVCMOS12_JEDEC))
dev->u.iob.drive_strength = 6;
else
dev->u.iob.drive_strength = 8;
dev->u.iob.slew = SLEW_SLOW;
}
dev->instantiated = 1;
return 0;
fail:

View File

@ -78,8 +78,10 @@ int fdev_logic_cout_used(struct fpga_model* model, int y, int x,
int fdev_logic_precyinit(struct fpga_model* model, int y, int x,
int type_idx, int precyinit);
int fdev_iob_input(struct fpga_model* model, int y, int x, int type_idx);
int fdev_iob_output(struct fpga_model* model, int y, int x, int type_idx);
int fdev_iob_input(struct fpga_model* model, int y, int x,
int type_idx, const char* io_std);
int fdev_iob_output(struct fpga_model* model, int y, int x,
int type_idx, const char* io_std);
int fdev_set_required_pins(struct fpga_model* model, int y, int x, int type,
int type_idx);

View File

@ -366,7 +366,7 @@ const char* lut2bool(const uint64_t lut, int bits,
int printf_iob(uint8_t* d, int len, int inpos, int num_entries)
{
int i, j, num_printed;
int i, num_printed;
uint64_t u64;
num_printed = 0;
@ -375,10 +375,6 @@ int printf_iob(uint8_t* d, int len, int inpos, int num_entries)
if (u64) {
printf("iob i%i 0x%016llX\n", i,
(long long unsigned) u64);
for (j = 0; j < 64; j++) {
if (u64 & (1ULL << j))
printf("iob i%i b%i\n", i, j);
}
num_printed++;
}
}

View File

@ -445,8 +445,16 @@ struct fpgadev_logic
enum { IOBM = 1, IOBS };
typedef char IOSTANDARD[32];
#define IO_LVCMOS33 "LVCMOS33"
#define IO_SSTL2_I "SSTL2_I" // drive attr and slew not used here?
#define IO_LVTTL "LVTTL"
#define IO_LVCMOS33 "LVCMOS33"
#define IO_LVCMOS25 "LVCMOS25"
#define IO_LVCMOS18 "LVCMOS18"
#define IO_LVCMOS18_JEDEC "LVCMOS18_JEDEC"
#define IO_LVCMOS15 "LVCMOS15"
#define IO_LVCMOS15_JEDEC "LVCMOS15_JEDEC"
#define IO_LVCMOS12 "LVCMOS12"
#define IO_LVCMOS12_JEDEC "LVCMOS12_JEDEC"
#define IO_SSTL2_I "SSTL2_I" // TODO: sstl not fully supported
enum { BYPASS_MUX_I = 1, BYPASS_MUX_O, BYPASS_MUX_T };
enum { IMUX_I_B = 1, IMUX_I };
enum { SLEW_SLOW = 1, SLEW_FAST, SLEW_QUIETIO };

View File

@ -41,25 +41,64 @@
#define XC6_HCLK_BYTES 2
#define XC6_HCLK_BITS (XC6_HCLK_BYTES*8)
#define XC6_IOB_MASK_INSTANTIATED 0x0000000000000080
#define XC6_IOB_MASK_IO 0x00FF00FF00000000
#define XC6_IOB_MASK_O_PINW 0x0000000000000100
#define XC6_IOB_MASK_I_MUX 0x000000000000E400
#define XC6_IOB_MASK_IO 0x00FF00FFFF000000
#define XC6_IOB_MASK_IN_TYPE 0x000000000000F000
#define XC6_IOB_MASK_SLEW 0x0000000000FF0000
#define XC6_IOB_MASK_SUSPEND 0x000000000000001F
#define XC6_IOB_INSTANTIATED 0x0000000000000080
#define XC6_IOB_INPUT_LVCMOS33 0x00D0002400000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_2 0x001000B400000000
#define XC6_IOB_INPUT 0x00D0002400000000
#define XC6_IOB_INPUT_LVCMOS33_25_LVTTL 0x000000000000E000
#define XC6_IOB_INPUT_LVCMOS18_15_12 0x000000000000C000
#define XC6_IOB_INPUT_LVCMOS18_15_12_JEDEC 0x0000000000002000
#define XC6_IOB_INPUT_SSTL2_I 0x000000000000B000
#define XC6_IOB_OUTPUT_LVCMOS33_25_DRIVE_2 0x001000B400000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_4 0x0070006C00000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_6 0x003000FC00000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_8 0x0040000000000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_12 0x0060008800000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_16 0x009800C600000000
#define XC6_IOB_OUTPUT_LVCMOS33_DRIVE_24 0x0088007200000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_4 0x00B0006C00000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_6 0x004000FC00000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_8 0x0000000000000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_12 0x0058008800000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_16 0x00B800C600000000
#define XC6_IOB_OUTPUT_LVCMOS25_DRIVE_24 0x0054007200000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_2 0x009000B400000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_4 0x00F0006C00000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_6 0x007000FC00000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_8 0x0030000000000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_12 0x0080008800000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_16 0x006000C600000000
#define XC6_IOB_OUTPUT_LVTTL_DRIVE_24 0x0018007200000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_2 0x00F000B402000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_4 0x00C000AC02000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_6 0x00E000BC02000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_8 0x00D800A002000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_12 0x003800A802000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_16 0x002800A602000000
#define XC6_IOB_OUTPUT_LVCMOS18_DRIVE_24 0x00A400A202000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_2 0x00B0007402000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_4 0x00E0000C02000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_6 0x0098005C02000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_8 0x00C8003002000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_12 0x00F4001802000000
#define XC6_IOB_OUTPUT_LVCMOS15_DRIVE_16 0x002400D602000000
#define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_2 0x004000B402000000
#define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_4 0x0098006C02000000
#define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_6 0x008800FC02000000
#define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_8 0x0014000002000000
#define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_12 0x00FC008802000000
#define XC6_IOB_IMUX_I_B 0x0000000000000400
#define XC6_IOB_O_PINW 0x0000000000000100
#define XC6_IOB_IMUX_I 0x000000000000E000
#define XC6_IOB_IMUX_I_B 0x000000000000E400
#define XC6_IOB_SLEW_SLOW 0x0000000000000000
#define XC6_IOB_SLEW_FAST 0x0000000000330000
#define XC6_IOB_SLEW_QUIETIO 0x0000000000660000