Shop OBEX P1 Docs P2 Docs Learn Events
AHDL to Verilog — Parallax Forums

AHDL to Verilog

RamonRamon Posts: 484
edited 2014-08-14 15:01 in Propeller 1
Chip, are the files top.tdf and tim.tdf written in AHDL? or are they Altera specific?

I want to port the design to a xilinx XC3S1000 (s3board) ... and to Lattice in the future.

Please, if possible, can you convert them to verilog too?

(What is divide[].d ? the 16 / 5 clock signal? I don't understand this part.)

Comments

  • pik33pik33 Posts: 2,366
    edited 2014-08-13 08:02
    Divide is a vector of 13 flip-flops. It is simply a counter.

    In Verilog it should be something like this:


    reg[12:0] divide

    always @(posedge clk) divide<=divide+ (the rest of this thing translated to verilog)


    This is 13-bit counter which generates a clock for the Propeller according to its config. If it is rcslow, lowest bit is incremented every 160 MHz input clock tick. RCFAST or PLLx1 increments 8th bit etc. Then 11th bit is used as fake cog PLL clock and 12th bit is used as a cog clock.
  • RamonRamon Posts: 484
    edited 2014-08-13 08:49
    pik33 wrote: »
    divide<=divide+ (the rest of this thing translated to verilog)

    So it can be converted to verilog, right?
    I mean, this is not a altera/quartus specific file? (like top.qsf who contains pin assignments and compiler instructions)

    It could be possible/worthwhile to add comments to the code? Something like this:

    // Datasheet 1.4, page 14
    divide[].d = divide[].q + (
    cfgx[].q == b"11xx111" # res, // ( XINPUT + PLL16X ) or res,
    cfgx[].q == b"11xx110" & !res, // (XINPUT + PLL8X ) and !res,
    cfgx[].q == b"11xx101" & !res, // (XINPUT + PLL4X ) and !res,
    (cfgx[].q == b"11xx100" # cfgx[].q == b"xxxx000") & !res, // ( (XINPUT + PLL2X) or RCFAST ) and !res ),
    (cfgx[].q == b"11xx011" # cfgx[].q == b"x1xx010") & !res, // ( (XINPUT + PLL1X) or XTAL1 and !res ),
    b"0", // ?
    b"0", // ?
    b"0", // ?
    b"0", // ?
    b"0", // ?
    b"0", // ?
    b"0", // ?
    cfgx[].q == b"xxxx001" & !res // RCSLOW and !res
    );

    Is this correct?
  • pik33pik33 Posts: 2,366
    edited 2014-08-13 08:52
    Yes, all of this ahdl stuff can be rewritten in verilog.
    divide[].d = divide[].q + (
    cfgx[].q == b"11xx111" # res,      // ( XINPUT + PLL16X ) or res,                                                                                  // if reset high and cfg=xin+pllx16, add  1_0000_0000_0000 to divide
    cfgx[].q == b"11xx110" & !res,     // (XINPUT + PLL8X ) and !res,                                                                                // if reset high and cfg=xin+pllx8, add  0_1000_0000_0000 to divide
    cfgx[].q == b"11xx101" & !res,    //  (XINPUT + PLL4X ) and !res,                                                                                // if reset high and cfg=xin+pllx4, add  0_0100_0000_0000 to divide
    (cfgx[].q == b"11xx100" # cfgx[].q == b"xxxx000") & !res,   //  ( (XINPUT + PLL2X) or RCFAST ) and !res ),                  // if reset high and (cfg=xin+pllx2, or cfg=rcfast) add  0_0010_0000_0000 to divide
    (cfgx[].q == b"11xx011" # cfgx[].q == b"x1xx010") & !res,  //  ( (XINPUT + PLL1X) or XTAL1 and !res ),                        // if reset high and (cfg=xin+pllx1, or cfg=xtal1) add  0_0001_0000_0000 to divide
    b"0",    //                                                                                                                                                             //  always add zero at these bit position
    b"0",    // ?   
    b"0",    // ?
    b"0",    // ?
    b"0",    // ?
    b"0",    // ?
    b"0",    // ?
    cfgx[].q == b"xxxx001" & !res   // RCSLOW and !res                                                                                           // if reset high and cfg=RCSLOW add  0_0000_0000_0001 to divide
    

    Only one if can be true here so it always will add a number with only one "1" in it. The higher is this "1", the higher frequency will be outputted from divide[11] and divide[12]
  • cgraceycgracey Posts: 14,155
    edited 2014-08-13 10:29
    The P8X32A core is all in Verilog. The top.tdf and tim.tdf files are written in AHDL. They emulate the P8X32A clock and reset circuits, and also provide the PLL hookup for the 160MHz clk_pll and the 80MHz clk_cog dividers. As far as I've ever seen, AHDL is required (or maybe just used) for the top-level FPGA file in Altera projects. I think AHDL is necessary to involve Altera-specific things like PLLs into a design. Tim.tdf could be redone in Verilog, certainly, without any consequence, but I don't know about top.tdf. I just liked the idea of keeping the digital core in Verilog and then spoof what are the more analog-like functions (pll, digital clock dividers in lieu of full-custom analog clock multipliers) in AHDL.
  • KeithEKeithE Posts: 957
    edited 2014-08-13 10:39
    Chip another thing to potentially look into - can the Altera tools identify the use of $readmemh for specifiying ROM contents? Right now you're using pragmas (?) like (* ram_init_file = "hub_rom_high.hex" *) to specify ROM contents, but $readmemh would also work for Xilinx and for simulations.
  • pik33pik33 Posts: 2,366
    edited 2014-08-13 10:49
    Yes, $readmemh works.

    Edit: this was generated by Quartus for my PLL. Removed a bunch of comments at the end. I think PLLs for Xilinx have to be done in its environment.
    // megafunction wizard: %ALTPLL%
    // GENERATION: STANDARD
    // VERSION: WM1.0
    // MODULE: altpll 
    
    // ============================================================
    // File Name: pll2.v
    // Megafunction Name(s):
    //             altpll
    //
    // Simulation Library Files(s):
    //             altera_mf
    // ============================================================
    // ************************************************************
    // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
    //
    // 14.0.0 Build 200 06/17/2014 SJ Web Edition
    // ************************************************************
    
    
    //Copyright (C) 1991-2014 Altera Corporation. All rights reserved.
    //Your use of Altera Corporation's design tools, logic functions 
    //and other software and tools, and its AMPP partner logic 
    //functions, and any output files from any of the foregoing 
    //(including device programming or simulation files), and any 
    //associated documentation or information are expressly subject 
    //to the terms and conditions of the Altera Program License 
    //Subscription Agreement, the Altera Quartus II License Agreement,
    //the Altera MegaCore Function License Agreement, or other 
    //applicable license agreement, including, without limitation, 
    //that your use is for the sole purpose of programming logic 
    //devices manufactured by Altera and sold by Altera or its 
    //authorized distributors.  Please refer to the applicable 
    //agreement for further details.
    
    
    // synopsys translate_off
    `timescale 1 ps / 1 ps
    // synopsys translate_on
    module pll2 (
        inclk0,
        c0);
    
        input      inclk0;
        output      c0;
    
        wire [0:0] sub_wire2 = 1'h0;
        wire [4:0] sub_wire3;
        wire  sub_wire0 = inclk0;
        wire [1:0] sub_wire1 = {sub_wire2, sub_wire0};
        wire [0:0] sub_wire4 = sub_wire3[0:0];
        wire  c0 = sub_wire4;
    
        altpll    altpll_component (
                    .inclk (sub_wire1),
                    .clk (sub_wire3),
                    .activeclock (),
                    .areset (1'b0),
                    .clkbad (),
                    .clkena ({6{1'b1}}),
                    .clkloss (),
                    .clkswitch (1'b0),
                    .configupdate (1'b0),
                    .enable0 (),
                    .enable1 (),
                    .extclk (),
                    .extclkena ({4{1'b1}}),
                    .fbin (1'b1),
                    .fbmimicbidir (),
                    .fbout (),
                    .fref (),
                    .icdrclk (),
                    .locked (),
                    .pfdena (1'b1),
                    .phasecounterselect ({4{1'b1}}),
                    .phasedone (),
                    .phasestep (1'b1),
                    .phaseupdown (1'b1),
                    .pllena (1'b1),
                    .scanaclr (1'b0),
                    .scanclk (1'b0),
                    .scanclkena (1'b1),
                    .scandata (1'b0),
                    .scandataout (),
                    .scandone (),
                    .scanread (1'b0),
                    .scanwrite (1'b0),
                    .sclkout0 (),
                    .sclkout1 (),
                    .vcooverrange (),
                    .vcounderrange ());
        defparam
            altpll_component.bandwidth_type = "AUTO",
            altpll_component.clk0_divide_by = 5,
            altpll_component.clk0_duty_cycle = 50,
            altpll_component.clk0_multiply_by = 14,
            altpll_component.clk0_phase_shift = "0",
            altpll_component.compensate_clock = "CLK0",
            altpll_component.inclk0_input_frequency = 20000,
            altpll_component.intended_device_family = "Cyclone IV E",
            altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll2",
            altpll_component.lpm_type = "altpll",
            altpll_component.operation_mode = "NORMAL",
            altpll_component.pll_type = "AUTO",
            altpll_component.port_activeclock = "PORT_UNUSED",
            altpll_component.port_areset = "PORT_UNUSED",
            altpll_component.port_clkbad0 = "PORT_UNUSED",
            altpll_component.port_clkbad1 = "PORT_UNUSED",
            altpll_component.port_clkloss = "PORT_UNUSED",
            altpll_component.port_clkswitch = "PORT_UNUSED",
            altpll_component.port_configupdate = "PORT_UNUSED",
            altpll_component.port_fbin = "PORT_UNUSED",
            altpll_component.port_inclk0 = "PORT_USED",
            altpll_component.port_inclk1 = "PORT_UNUSED",
            altpll_component.port_locked = "PORT_UNUSED",
            altpll_component.port_pfdena = "PORT_UNUSED",
            altpll_component.port_phasecounterselect = "PORT_UNUSED",
            altpll_component.port_phasedone = "PORT_UNUSED",
            altpll_component.port_phasestep = "PORT_UNUSED",
            altpll_component.port_phaseupdown = "PORT_UNUSED",
            altpll_component.port_pllena = "PORT_UNUSED",
            altpll_component.port_scanaclr = "PORT_UNUSED",
            altpll_component.port_scanclk = "PORT_UNUSED",
            altpll_component.port_scanclkena = "PORT_UNUSED",
            altpll_component.port_scandata = "PORT_UNUSED",
            altpll_component.port_scandataout = "PORT_UNUSED",
            altpll_component.port_scandone = "PORT_UNUSED",
            altpll_component.port_scanread = "PORT_UNUSED",
            altpll_component.port_scanwrite = "PORT_UNUSED",
            altpll_component.port_clk0 = "PORT_USED",
            altpll_component.port_clk1 = "PORT_UNUSED",
            altpll_component.port_clk2 = "PORT_UNUSED",
            altpll_component.port_clk3 = "PORT_UNUSED",
            altpll_component.port_clk4 = "PORT_UNUSED",
            altpll_component.port_clk5 = "PORT_UNUSED",
            altpll_component.port_clkena0 = "PORT_UNUSED",
            altpll_component.port_clkena1 = "PORT_UNUSED",
            altpll_component.port_clkena2 = "PORT_UNUSED",
            altpll_component.port_clkena3 = "PORT_UNUSED",
            altpll_component.port_clkena4 = "PORT_UNUSED",
            altpll_component.port_clkena5 = "PORT_UNUSED",
            altpll_component.port_extclk0 = "PORT_UNUSED",
            altpll_component.port_extclk1 = "PORT_UNUSED",
            altpll_component.port_extclk2 = "PORT_UNUSED",
            altpll_component.port_extclk3 = "PORT_UNUSED",
            altpll_component.width_clock = 5;
    
    
    endmodule
    
  • cgraceycgracey Posts: 14,155
    edited 2014-08-13 11:05
    KeithE wrote: »
    Chip another thing to potentially look into - can the Altera tools identify the use of $readmemh for specifiying ROM contents? Right now you're using pragmas (?) like (* ram_init_file = "hub_rom_high.hex" *) to specify ROM contents, but $readmemh would also work for Xilinx and for simulations.

    I just looked and, yes, Altera supports $readmemh.
  • KeithEKeithE Posts: 957
    edited 2014-08-13 11:22
    OK - then the real work would be converting Intel hex (?) into Verilog $readmemh format. This may have been done elsewhere in this forum or perhaps this could be easily adapted? http://read.pudn.com/downloads10/sourcecode/app/40626/minirisc/scode/hex2v.c__.htm
  • overclockedoverclocked Posts: 80
    edited 2014-08-13 12:19
    Already done these things. Read thread about Xilinx port.
  • RamonRamon Posts: 484
    edited 2014-08-14 06:29
    cgracey wrote: »
    The P8X32A core is all in Verilog. The top.tdf and tim.tdf files are written in AHDL. They emulate the P8X32A clock and reset circuits, and also provide the PLL hookup for the 160MHz clk_pll and the 80MHz clk_cog dividers. As far as I've ever seen, AHDL is required (or maybe just used) for the top-level FPGA file in Altera projects. I think AHDL is necessary to involve Altera-specific things like PLLs into a design. Tim.tdf could be redone in Verilog, certainly, without any consequence, but I don't know about top.tdf. I just liked the idea of keeping the digital core in Verilog and then spoof what are the more analog-like functions (pll, digital clock dividers in lieu of full-custom analog clock multipliers) in AHDL.

    Then we throw out PLL and "altpll.inc" from top.tdf, rewrite both AHDL files to Verilog, and just feed clock input with external clock (the same way as XINPUT mode : DC-80 MHz )

    Lattice has some small devices that even do not have a PLL. Is this is a double-edged sword for parallax business? Risk of P1 being replaced by small cplds or fpgas? or risk of links broken between Terasic and/or Altera?
  • Bill HenningBill Henning Posts: 6,445
    edited 2014-08-14 07:22
    I don't think that there are CPLD's big enough, and small FPGA's still cost a lot more than a P1.
    Ramon wrote: »
    Then we throw out PLL and "altpll.inc" from top.tdf, rewrite both AHDL files to Verilog, and just feed clock input with external clock (the same way as XINPUT mode : DC-80 MHz )

    Lattice has some small devices that even do not have a PLL. Is this is a double-edged sword for parallax business? Risk of P1 being replaced by small cplds or fpgas? or risk of links broken between Terasic and/or Altera?
  • pik33pik33 Posts: 2,366
    edited 2014-08-14 08:40
    Ramon wrote: »
    Then we throw out PLL and "altpll.inc" from top.tdf, rewrite both AHDL files to Verilog, and just feed clock input with external clock (the same way as XINPUT mode : DC-80 MHz )

    Lattice has some small devices that even do not have a PLL. Is this is a double-edged sword for parallax business? Risk of P1 being replaced by small cplds or fpgas? or risk of links broken between Terasic and/or Altera?

    You don't need a pll. You only need a clock which is 2x the Propeller clock. You have 50 MHz input clock in Altera boards, which, without PLL, gives you 25 MHz clocked Propeller. The pll is used only for making 160 MHz clock for the simulated chip.

    I want now to get rid of this pll inside the Propeller and feed it from outside, which can give me an option to make a variable frequency generator switched via for example SWxx on DE2-115. This will give me oprion to have the Propeller running @ std 80 MHz or 100, or 120, or 140 MHz without reprogramming the FPGA.
  • overclockedoverclocked Posts: 80
    edited 2014-08-14 09:32
    Cool idea. Well just do it! Another question Is there a problem with running cog and all clock all the same?
  • cgraceycgracey Posts: 14,155
    edited 2014-08-14 09:41
    Cool idea. Well just do it! Another question Is there a problem with running cog and all clock all the same?


    You can run them both off the same clock.

    The only reason the clk_pll was twice as fast as clk_cog was to reduce jitter. 4x or 8x would have been even better.
  • pik33pik33 Posts: 2,366
    edited 2014-08-14 09:47
    cgracey wrote: »
    You can run them both off the same clock.

    The only reason the clk_pll was twice as fast as clk_cog was to reduce jitter. 4x or 8x would have been even better.

    I tried this, but it needs some changes. When I run the Propeller clock and PLL clock from the same 140 MHz source, the output frequency for the video was 2x too slow and in spin code I had to set _clkfreq to 70 MHz
  • cgraceycgracey Posts: 14,155
    edited 2014-08-14 10:04
    pik33 wrote: »
    I tried this, but it needs some changes. When I run the Propeller clock and PLL clock from the same 140 MHz source, the output frequency for the video was 2x too slow and in spin code I had to set _clkfreq to 70 MHz


    You'll need to go into ctr.v and alter this line:

    wire [7:0] pll_taps = pll_fake[35:28];

    to be like this:

    wire [7:0] pll_taps = pll_fake[34:27];

    There may be a problem without at least a 2x clock for the pll_fake registers, where some larger FRQ values won't work because they can't accumulate fast enough.
  • Cluso99Cluso99 Posts: 18,069
    edited 2014-08-14 15:01
    KeithE wrote: »
    OK - then the real work would be converting Intel hex (?) into Verilog $readmemh format. This may have been done elsewhere in this forum or perhaps this could be easily adapted? http://read.pudn.com/downloads10/sourcecode/app/40626/minirisc/scode/hex2v.c__.htm
    I have all of the data in the ROM converted and outputting to a file in hex. I was just waiting on Chip to answer the last question about the "unused" portions of the ROM and he has done this today.
    I will post the new ROM file(s) and the spin program that produces these shortly - unscrambled and $00 for the unused parts. Everything is here on this thread
    http://forums.parallax.com/showthread.php/156866-Question-for-Chip-re-ROM-code

    I will look at the link you posted in more detail once I have completed this part.
Sign In or Register to comment.