Forum: FPGA, VHDL & Co. CAN Module von opencores


von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

Hallo!

In einem aktuellen Projekt verwende ich das CAN Modul von opencores:
http://opencores.org/websvn,listing?repname=can&path=&;

Das FPGA das ich verwende ist ein Spartan 6. Leider wird in der Datei 
can_fifo.v Block Ram instantiert, den es so im Spartan 6 nicht mehr 
gibt:
1
 RAMB4_S8_S8 fifo
2
  (
3
    .DOA(),
4
    .DOB(data_out),
5
    .ADDRA({3'h0, wr_pointer}),
6
    .CLKA(clk),
7
    .DIA(data_in),
8
    .ENA(1'b1),
9
    .RSTA(1'b0),
10
    .WEA(wr & (~fifo_full)),
11
    .ADDRB({3'h0, read_address}),
12
    .CLKB(clk),
13
    .DIB(8'h0),
14
    .ENB(1'b1),
15
    .RSTB(1'b0),
16
    .WEB(1'b0)
17
  );
18
 
19
 
20
  RAMB4_S4_S4 info_fifo
21
  (
22
    .DOA(),
23
    .DOB(length_info),
24
    .ADDRA({4'h0, wr_info_pointer}),
25
    .CLKA(clk),
26
    .DIA(len_cnt & {4{~initialize_memories}}),
27
    .ENA(1'b1),
28
    .RSTA(1'b0),
29
    .WEA(write_length_info & (~info_full) | initialize_memories),
30
    .ADDRB({4'h0, rd_info_pointer}),
31
    .CLKB(clk),
32
    .DIB(4'h0),
33
    .ENB(1'b1),
34
    .RSTB(1'b0),
35
    .WEB(1'b0)
36
  );
37
 
38
 
39
  RAMB4_S1_S1 overrun_fifo
40
  (
41
    .DOA(),
42
    .DOB(overrun),
43
    .ADDRA({6'h0, wr_info_pointer}),
44
    .CLKA(clk),
45
    .DIA((latch_overrun | (wr & fifo_full)) & (~initialize_memories)),
46
    .ENA(1'b1),
47
    .RSTA(1'b0),
48
    .WEA(write_length_info & (~info_full) | initialize_memories),
49
    .ADDRB({6'h0, rd_info_pointer}),
50
    .CLKB(clk),
51
    .DIB(1'h0),
52
    .ENB(1'b1),
53
    .RSTB(1'b0),
54
    .WEB(1'b0)
55
  );

Hier der Link zur Datei:
http://opencores.org/websvn,filedetails?repname=can&path=%2Fcan%2Ftrunk%2Frtl%2Fverilog%2Fcan_fifo.v

Da ich kein Verilog spreche wollte ich fragen, ob Ihr mir helfen könnt. 
Wie kann ich den BlockRam ersetzen?

Die erste Frage die ich mir stelle wenn ich in den Libraries Guide für 
das Spartan 6 gucke ist: Was bedeutet das # am Anfang des 
instantiierungstemplate? Und wie sorge ich dafür, dass die Busbreiten 
richtig übernommen werden?
1
.DATA_WIDTH_A(n), // n muss bei mir wohl 1, 4 oder 8(9) sein
2
.DATA_WIDTH_B(n),

Wenn ich für DATA_WIDTH Werte eintrage sind die Signalbreiten immer 16 
bit...

Gruß,

     Hendrik

von berndl (Gast)


Lesenswert?

nimm doch einfach die RAM Version die 'abstakt' definiert ist:
`ifdef VIRTUALSILICON_RAM

ISE sollte damit klarkommen. Wenn nicht, kannst du ja das eigentliche 
RAM auch in VHDL bauen (Instanz oder generisch in VHDL).

Und das # steht in Verilog m.W. fuer Delay, also wie bei VHDL ... after 
X ns

von bko (Gast)


Lesenswert?

nicht nur
>Und das # steht in Verilog m.W. fuer Delay, also wie bei VHDL ... after
>X ns

sondern # wird auch auch bei der Parameterübergabe an Module benutzt:
[code]
param_ram_syncread #(.addrl(15),  //modul instantiierung+
                     .datal(8))   // 2x parameter
              ram (               // modul name
                   .clk(!clk),    // ports
                   .write(write), .read(read),
       ...

module param_ram_syncread(        // modul beschreibung
                  clk,
                  write,
                  read, ...


   parameter addrl=8;
   parameter datal=8;

   input   clk;
   input   write;

   ...
[/code)

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

berndl schrieb:
> nimm doch einfach die RAM Version die 'abstakt' definiert ist:
> `ifdef VIRTUALSILICON_RAM

... wer lesen kann ist klar im Vorteil...
Ich probier's Montag mal aus.


Gruß und schönes WE,

    Hendrik

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

berndl schrieb:
> nimm doch einfach die RAM Version die 'abstakt' definiert ist:
> `ifdef VIRTUALSILICON_RAM

Dann bekomme ich:

ERROR:HDLCompiler:1654 - 
"/home/likewise-open/DFKI/hhanff/proj/110909_FPGA.svn/lib/CAN_Controller 
/trunk/can_fifo.v"  Line 858: Instantiating <fifo> from unknown module 
<vs_hdtp_64x8>

:-/

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

bko schrieb:
> # wird auch auch bei der Parameterübergabe an Module benutzt:
>
1
> param_ram_syncread #(.addrl(15),  //modul instantiierung+
2
>                      .datal(8))   // 2x parameter
3
>               ram (               // modul name
4
>                    .clk(!clk),    // ports
5
>                    .write(write), .read(read),
6
>        ...
7
> 
8
> module param_ram_syncread(        // modul beschreibung
9
>                   clk,
10
>                   write,
11
>                   read, ...
12
> 
13
> 
14
>    parameter addrl=8;
15
>    parameter datal=8;
16
> 
17
>    input   clk;
18
>    input   write;
19
> 
20
>    ...
21
>

Das heisst wenn ich mehrere Instanzen eines Moduls haben möchte und 
diesen Instanzen unterschiedliche Werte übergeben möchte muss ich der 
Instantiierung nur einen Block mit '#' voranstellen?

Dein Beispiel mit unterschiedlichen Parametern würde dann so aussehen:
1
param_ram_syncread #(.addrl(15),  //modul instantiierung+
2
                     .datal(8))   // 2x parameter
3
              ram (               // modul name
4
                   .clk(!clk),    // ports
5
                   .write(write), .read(read),
6
       ...
7
8
param_ram_syncread #(.addrl(8),  //modul instantiierung+
9
                     .datal(16))   // 2x parameter
10
              ram (               // modul name
11
                   .clk(!clk),    // ports
12
                   .write(write), .read(read),
13
       ...

Ist das richtig???

von Duke Scarring (Gast)


Lesenswert?

Heinrich H. schrieb:
> ERROR:HDLCompiler:1654 -
> "/home/likewise-open/DFKI/hhanff/proj/110909_FPGA.svn/lib/CAN_Controller 
/trunk/can_fifo.v"
> Line 858: Instantiating <fifo> from unknown module <vs_hdtp_64x8>

Das scheint lt. can_defines.v auch eher der Holzweg zu sein:
1
// Uncomment the line for the ram used in ASIC implementation
2
// `define   VIRTUALSILICON_RAM
3
// `define   ARTISAN_RAM
4
 
5
// Uncomment the following line when RAM BIST is needed (ASIC implementation)
6
//`define CAN_BIST                    // Bist (for ASIC implementation)

Wie lautet denn die konkrete Fehlermeldung, wenn Du XILINX_RAM 
verwendest?

Duke

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

Duke Scarring schrieb:
> Wie lautet denn die konkrete Fehlermeldung, wenn Du XILINX_RAM
> verwendest?

Hallo Duke!

Die Fehlermeldung lautet:
1
ERROR:NgdBuild:604 - logical block
2
   'NodeCommunicationInterface_CAN_1/can0/can_device/can_module/i_can_bsp/i_can_
3
   fifo/overrun_fifo' with type 'RAMB4_S1_S1' could not be resolved. A pin name
4
   misspelling can cause this, a missing edif or ngc file, case mismatch between
5
   the block name and the edif or ngc file name, or the misspelling of a type
6
   name. Symbol 'RAMB4_S1_S1' is not supported in target 'spartan6'.
7
ERROR:NgdBuild:604 - logical block
8
   'NodeCommunicationInterface_CAN_1/can0/can_device/can_module/i_can_bsp/i_can_
9
   fifo/info_fifo' with type 'RAMB4_S4_S4' could not be resolved. A pin name
10
   misspelling can cause this, a missing edif or ngc file, case mismatch between
11
   the block name and the edif or ngc file name, or the misspelling of a type
12
   name. Symbol 'RAMB4_S4_S4' is not supported in target 'spartan6'.
13
ERROR:NgdBuild:604 - logical block
14
   'NodeCommunicationInterface_CAN_1/can0/can_device/can_module/i_can_bsp/i_can_
15
   fifo/fifo' with type 'RAMB4_S8_S8' could not be resolved. A pin name
16
   misspelling can cause this, a missing edif or ngc file, case mismatch between
17
   the block name and the edif or ngc file name, or the misspelling of a type
18
   name. Symbol 'RAMB4_S8_S8' is not supported in target 'spartan6'.

von Heinrich H. (Firma: Ich.AG) (hhanff)


Lesenswert?

Ich verstehe nicht recht warum, obwohl ich im Beispiel unten die 
Busbreiten für die Ports A und B mit 4 angegeben habe
1
.DATA_WIDTH_A(4),
2
.DATA_WIDTH_B(4),
, der Datenport DOBDO dann doch 16 Bit breit ist...
1
   // RAMB8BWER: 8k-bit Data and 1k-bit Parity Configurable Synchronous Block RAM
2
   //            Spartan-6
3
   // Xilinx HDL Language Template, version 13.2
4
   RAMB8BWER #(
5
      // DATA_WIDTH_A/DATA_WIDTH_B: 'If RAM_MODE="TDP": 0, 1, 2, 4, 9 or 18; If RAM_MODE="SDP": 36'
6
      .DATA_WIDTH_A(4), // <- ****** HIER BUSBREITE = 4 ******
7
      .DATA_WIDTH_B(4), // <- ****** HIER BUSBREITE = 4 ******
8
      // DOA_REG/DOB_REG: Optional output register (0 or 1)
9
      .DOA_REG(0),
10
      .DOB_REG(0),
11
      // EN_RSTRAM_A/EN_RSTRAM_B: Enable/disable RST
12
      .EN_RSTRAM_A("TRUE"),
13
      .EN_RSTRAM_B("TRUE"),
14
      // INITP_00 to INITP_03: Initial memory contents.
15
[....]
16
.INIT_FILE("NONE"),                                                               // Do not modify
17
      // RAM_MODE: "SDP" or "TDP" 
18
      .RAM_MODE("TDP"),
19
      // RSTTYPE: "SYNC" or "ASYNC" 
20
      .RSTTYPE("SYNC"),
21
      // RST_PRIORITY_A/RST_PRIORITY_B: "CE" or "SR" 
22
      .RST_PRIORITY_A("CE"),
23
      .RST_PRIORITY_B("CE"),
24
      // SIM_COLLISION_CHECK: Collision check enable "ALL", "WARNING_ONLY", "GENERATE_X_ONLY" or "NONE" 
25
      .SIM_COLLISION_CHECK("NONE"),
26
      // SRVAL_A/SRVAL_B: Set/Reset value for RAM output
27
      .SRVAL_A(18'h00000),
28
      .SRVAL_B(18'h00000),
29
      // WRITE_MODE_A/WRITE_MODE_B: "WRITE_FIRST", "READ_FIRST", or "NO_CHANGE" 
30
      .WRITE_MODE_A("WRITE_FIRST"),
31
      .WRITE_MODE_B("WRITE_FIRST") 
32
   )
33
   RAMB8BWER_inst_info_fifo(
34
      // Port A Data: 16-bit (each) output: Port A data
35
      .DOADO(),             // 16-bit output: A port data/LSB data output
36
      .DOPADOP(),         // 2-bit output: A port parity/LSB parity output
37
      // Port B Data: 16-bit (each) output: Port B data
38
      .DOBDO({length_info_16}),             // 16-bit output: B port data/MSB data output
39
      .DOPBDOP(),         // 2-bit output: B port parity/MSB parity output
40
      // Port A Address/Control Signals: 13-bit (each) input: Port A address and control signals (write port
41
      // when RAM_MODE="SDP")
42
      .ADDRAWRADDR({7'h0, wr_info_pointer}), // 13-bit input: A port address/Write address input
43
      .CLKAWRCLK(clk),     // 1-bit input: A port clock/Write clock input
44
      .ENAWREN(1'b1),         // 1-bit input: A port enable/Write enable input
45
      .REGCEA(1'b1),           // 1-bit input: A port register enable input
46
      .RSTA(1'b0),               // 1-bit input: A port set/reset input
47
      .WEAWEL({1'b0,write_length_info & (~info_full) | initialize_memories}),           // 2-bit input: A port write enable input
48
      // Port A Data: 16-bit (each) input: Port A data
49
      .DIADI({12'h0,len_cnt & {4{~initialize_memories}}}),             // 16-bit input: A port data/LSB data input
50
      .DIPADIP(),         // 2-bit input: A port parity/LSB parity input
51
      // Port B Address/Control Signals: 13-bit (each) input: Port B address and control signals (read port
52
      // when RAM_MODE="SDP")
53
      .ADDRBRDADDR({7'h0, rd_info_pointer}), // 13-bit input: B port address/Read address input
54
      .CLKBRDCLK(clk),     // 1-bit input: B port clock/Read clock input
55
      .ENBRDEN(1'b1),         // 1-bit input: B port enable/Read enable input
56
      .REGCEBREGCE(1'b1), // 1-bit input: B port register enable/Register enable input
57
      .RSTBRST(1'b0),         // 1-bit input: B port set/reset input
58
      .WEBWEU(2'b0),           // 2-bit input: B port write enable input
59
      // Port B Data: 16-bit (each) input: Port B data
60
      .DIBDI(16'h0),             // 16-bit input: B port data/MSB data input
61
      .DIPBDIP(2'h0)          // 2-bit input: B port parity/MSB parity input
62
   );

von Duke Scarring (Gast)


Lesenswert?

Hier ist mal ein Ersatz für das RAMB4_S8_S8-Makro:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity spartan6_ramb4_s8_s8 is
6
    port(
7
        doa   : out std_logic_vector(7 downto 0);
8
        dob   : out std_logic_vector(7 downto 0);
9
        --
10
        addra : in  std_logic_vector(8 downto 0);
11
        addrb : in  std_logic_vector(8 downto 0);
12
        clka  : in  std_ulogic;
13
        clkb  : in  std_ulogic;
14
        dia   : in  std_logic_vector(7 downto 0);
15
        dib   : in  std_logic_vector(7 downto 0);
16
        ena   : in  std_ulogic;
17
        enb   : in  std_ulogic;
18
        rsta  : in  std_ulogic;
19
        rstb  : in  std_ulogic;
20
        wea   : in  std_ulogic;
21
        web   : in  std_ulogic
22
        );
23
end entity spartan6_ramb4_s8_s8;
24
25
26
architecture syn of spartan6_ramb4_s8_s8 is
27
28
    type ram_type is array (511 downto 0) of std_logic_vector(7 downto 0);
29
    shared variable ram : ram_type;
30
31
begin
32
33
    process (clka)
34
    begin
35
        if rising_edge(clka) then
36
            if ena = '1' then
37
                if rsta = '1' then
38
                    doa <= (others => '0');
39
                else
40
                    doa <= ram(to_integer(unsigned(addra)));
41
                end if;
42
                if wea = '1' then
43
                    ram(to_integer(unsigned(addra))) := dia;
44
                end if;
45
            end if;
46
        end if;
47
    end process;
48
49
    process (clkb)
50
    begin
51
        if rising_edge(clkb) then
52
            if enb = '1' then
53
                if rstb = '1' then
54
                    dob <= (others => '0');
55
                else
56
                    dob <= ram(to_integer(unsigned(addrb)));
57
                end if;
58
                if web = '1' then
59
                    ram(to_integer(unsigned(addrb))) := dib;
60
                end if;
61
            end if;
62
        end if;
63
    end process;
64
    
65
end architecture syn;
Das ist aus dem XST User Guide Examples abgeleitet und läßt sich mit XST 
zu einem BRAM synthetisieren. Dort stehen auch die verilog-Varianten. 
Die anderen beiden fehlenden Makros kannst Du Dir leicht selber davon 
ableiten.

Duke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.