Electronics > FPGA

Reverse engineering Anlogic AL3_10 FPGA

<< < (7/19) > >>

pcprogrammer:
Today I managed to generate the pin constraint file and the main module with the external signal names.

The code recognizes the bits for slew rate and pull type and can determine if a pin is set for input or output when not connected to any visible routes. This is the case for the clock input pin. It connects directly to the pll, but I can't tell which bits are set to make this work.

For now I will manually configure the global clock connections because I already examined what these connections are.

Next up is generating code for the logic slices. I will have to test with several scenarios if the correct code is generated.

I do feel things are on the right track, but still have a lot to do before proper top level verilog is obtained, because gate level verilog is not very useful, other then giving the ability to re generate the bit stream. Making modifications to the design on that level is not really doable.

It does help with interpreting the setting bits though.

pcprogrammer:
Hmm, hit a bit of a snafu |O

Simply translating the logic blocks in either AL_PHY_MSLICE or AL_PHY_LSLICE macro does not lead to the same bit stream when run through the IDE again. There are quite a bit of different functions a slice can have and to get the exact same bit stream the logic has to be mapped to the correct functional macro.

For instance when a simple two input AND gate is intended, an AL_MAP_LUT2 is needed and the logic equation needs to be given like (B*A). This means that the lookup table has to be examined together with the used inputs to find the correct equation. Not to hard for a two input function, but more so when it is a 5 or even 6 input one.

Getting the bits set in the lookup table is easy and already implemented. Now I have to write a lot of code to determine the type of macro to use for the slice or part of the slice, and then, when needed, make up the correct equation for it.

A well, it is all part of the adventure I embarked on :)

pcprogrammer:
There is still  lot of work to be done, but I'm getting some output.

I made a simple design in verilog to see what the different types of logic would do in the setting bits. With the IDE it is possible to make gate level verilog for simulation, which gives a good insight in to what I need to produce.

The verilog used to make the bit stream.

--- Code: ---module pin_test
(
  input  wire i_led_red_control,
  input  wire i_led_blue_control, 
  input  wire i_led_yellow_control,
  output wire o_led_red, 
  output wire o_led_blue, 
  output wire o_led_green,
  output wire o_led_yellow
);

reg ireg_red_led = 0;

always@(posedge i_led_red_control)
  begin
    ireg_red_led <= ~(i_led_blue_control | i_led_yellow_control);
  end

assign o_led_yellow = (~i_led_yellow_control & (i_led_red_control & i_led_blue_control)) | (i_led_yellow_control & (i_led_red_control ^ i_led_blue_control));
assign o_led_red    = i_led_red_control | i_led_blue_control;
assign o_led_blue   = i_led_red_control ^ i_led_blue_control;

assign o_led_green = ireg_red_led;

endmodule

--- End code ---

The gate level output from the IDE

--- Code: ---// Verilog netlist created by TD v5.0.28716
// Thu Sep 22 20:04:13 2022

`timescale 1ns / 1ps
module pin_test  // pin_test.v(1)
  (
  i_led_blue_control,
  i_led_red_control,
  i_led_yellow_control,
  o_led_blue,
  o_led_green,
  o_led_red,
  o_led_yellow
  );

  input i_led_blue_control;  // pin_test.v(4)
  input i_led_red_control;  // pin_test.v(3)
  input i_led_yellow_control;  // pin_test.v(5)
  output o_led_blue;  // pin_test.v(7)
  output o_led_green;  // pin_test.v(8)
  output o_led_red;  // pin_test.v(6)
  output o_led_yellow;  // pin_test.v(9)

  wire i_led_blue_control_pad;  // pin_test.v(4)
  wire i_led_red_control_pad;  // pin_test.v(3)
  wire i_led_yellow_control_pad;  // pin_test.v(5)
  wire n1;
  wire o_led_blue_pad;  // pin_test.v(7)
  wire o_led_green_pad;  // pin_test.v(8)
  wire o_led_red_pad;  // pin_test.v(6)
  wire o_led_yellow_pad;  // pin_test.v(9)

  AL_PHY_PAD #(
    //.LOCATION("P88"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("NONE"),
    .IOTYPE("LVCMOS33"),
    .MODE("IN"),
    .TSMUX("1"))
    _al_u0 (
    .ipad(i_led_blue_control),
    .di(i_led_blue_control_pad));  // pin_test.v(4)
  AL_PHY_PAD #(
    //.LOCATION("P28"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("NONE"),
    .IOTYPE("LVCMOS33"),
    .MODE("IN"),
    .TSMUX("1"))
    _al_u1 (
    .ipad(i_led_red_control),
    .di(i_led_red_control_pad));  // pin_test.v(3)
  AL_MAP_LUT2 #(
    .EQN("(~B*~A)"),
    .INIT(4'h1))
    _al_u10 (
    .a(i_led_blue_control_pad),
    .b(i_led_yellow_control_pad),
    .o(n1));
  AL_PHY_PAD #(
    //.LOCATION("P31"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("NONE"),
    .IOTYPE("LVCMOS33"),
    .MODE("IN"),
    .TSMUX("1"))
    _al_u2 (
    .ipad(i_led_yellow_control),
    .di(i_led_yellow_control_pad));  // pin_test.v(5)
  AL_PHY_PAD #(
    //.LOCATION("P49"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("PULLDOWN"),
    //.SLEWRATE("MED"),
    .DRIVE("8"),
    .IOTYPE("LVCMOS33"),
    .MODE("OUT"),
    .TSMUX("0"))
    _al_u3 (
    .otrue(o_led_blue_pad),
    .opad(o_led_blue));  // pin_test.v(7)
  AL_PHY_PAD #(
    //.LOCATION("P39"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("NONE"),
    //.SLEWRATE("SLOW"),
    .DRIVE("8"),
    .IOTYPE("LVCMOS33"),
    .MODE("OUT"),
    .TSMUX("0"))
    _al_u4 (
    .otrue(o_led_green_pad),
    .opad(o_led_green));  // pin_test.v(8)
  AL_PHY_PAD #(
    //.LOCATION("P112"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("KEEPER"),
    //.SLEWRATE("FAST"),
    .DRIVE("8"),
    .IOTYPE("LVCMOS33"),
    .MODE("OUT"),
    .TSMUX("0"))
    _al_u5 (
    .otrue(o_led_red_pad),
    .opad(o_led_red));  // pin_test.v(6)
  AL_PHY_PAD #(
    //.LOCATION("P34"),
    //.PCICLAMP("OFF"),
    //.PULLMODE("NONE"),
    //.SLEWRATE("SLOW"),
    .DRIVE("8"),
    .IOTYPE("LVCMOS33"),
    .MODE("OUT"),
    .TSMUX("0"))
    _al_u6 (
    .otrue(o_led_yellow_pad),
    .opad(o_led_yellow));  // pin_test.v(9)
  AL_MAP_LUT2 #(
    .EQN("~(~B*~A)"),
    .INIT(4'he))
    _al_u7 (
    .a(i_led_blue_control_pad),
    .b(i_led_red_control_pad),
    .o(o_led_red_pad));
  AL_MAP_LUT2 #(
    .EQN("(B@A)"),
    .INIT(4'h6))
    _al_u8 (
    .a(i_led_blue_control_pad),
    .b(i_led_red_control_pad),
    .o(o_led_blue_pad));
  AL_MAP_LUT3 #(
    .EQN("(A*B*~(C)+A*~(B)*C+~(A)*B*C)"),
    .INIT(8'h68))
    _al_u9 (
    .a(i_led_blue_control_pad),
    .b(i_led_red_control_pad),
    .c(i_led_yellow_control_pad),
    .o(o_led_yellow_pad));
  AL_MAP_SEQ #(
    .CEMUX("1"),
    .CLKMUX("CLK"),
    .DFFMODE("FF"),
    .REGSET("RESET"),
    .SRMODE("ASYNC"),
    .SRMUX("0"))
    ireg_red_led_reg (
    .clk(i_led_red_control_pad),
    .d(n1),
    .q(o_led_green_pad));  // pin_test.v(14)
endmodule

--- End code ---

What comes back from my code so far.

--- Code: ---module pin_test
(
  output wire o_led_yellow,
  input wire i_led_yellow_control,
  input wire i_led_red_control,
  output wire o_led_green,
  output wire o_led_blue,
  output wire o_led_red,
  input wire i_led_blue_control
);

  AL_MAP_LUT2 #
  (
    .EQN("B@A")
  )
  _al_block_18_lut_0
  (
    .a(x0y10_pin_28_di_net_3),
    .b(x34y16_pin_88_di_net_8),
    .o(x10y5_mslice1_f_0_net_6)
  );

  AL_MAP_LUT2 #
  (
    .EQN("B+A")
  )
  _al_block_23_lut_0
  (
    .a(x0y10_pin_28_di_net_3),
    .b(x34y16_pin_88_di_net_8),
    .o(x15y13_mslice1_f_0_net_7)
  );

endmodule

--- End code ---

The pin constraint file is fully generated, so the AL_PHY_PAD macros are not needed and would give problems with the pin assignment as written before. But I do need to list the wires and output assigns to connect the internally used wires to the external wires.

The target for now is to get these "simple" logic parts generated and check if it produces the same bit stream as the original.

For the equations I'm using a lookup table for two inputs and for more inputs I will make combinations based on NOT, AND and OR logic.

The fact that there are two LUT's and flip flops per slice makes it more complex to derive all the needed verilog marcos from the settings, but with a step by step approach I will get there. But it involves a lot of probing a black box, due to the lack of documentation. But that is something the FPGA manufactures don't want out in the world. In depth information about their products :(

pcprogrammer:
A first test showed some success. The two files generated so far (gate level verilog and pin constraint) allow me to generate a new bit stream, but for some reason the router swaps some of the logic between the two available parts in a slice.

It uses the same tiles and slices, but instead of using the flip flop connected to LUT0 it uses the one connected to LUT1 to make up the register from the original code. It sets the same number of bits to on and when I run the bit stream through my code again it looks the same, except for the swap of the two LUT's and flip flop. :palm:

I now have to see if this is also going to be the case with the actual FNIRSI-1013D bit stream, but before I can run that I need to implement a lot more code, and run lots of other tests.

pcprogrammer:
Managed to solve the LUT and flipflop swapping. Had to do with the naming of the AL_MAP_SEQ macro :o

The AL_MAP_LUT macros use names like _al_ and the AL_MAP_SEQ macro uses the name of the register given in the original design. This name is of course unknown, but when I name it starting with reg_ instead of _al_ it fixes the swapping problem.

It was after this that I noticed another problem. The routing through the fabric was different and a better look at the generated verilog showed that signals where swapped on LUT inputs.

This is caused by the way I mapped the signals onto the AL_MAP_LUT macros, which seems to be the wrong way round. I assumed that the first input starting from the fabric input "a" would be the "a" input of the macro, but the output of my code shows that it is then swapped against to what the IDE generates for the gate level simulation. This means that the highest input either "mi", "e", or "d" depending on the slice and LUT configuration is the "a" input of the AL_MAP_LUT macro.

So some modification of the code is needed.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod