ã¿ãªããããã«ã¡ã¯ïŒ
䜿çšãããŠããããã°ã©ãã³ã°èšèªããç§ãã¡ãããããããšã«å¶éã課ããéçºã«äžäŸ¿ãããããããšããããŸãã éçºè
ã¯ããã§äœãããŸããïŒ ãŸãã¯èªåèªèº«ãèŸä»»ããããã©ããããããç¶æ³ããè±åºããããšããŸãã
1ã€ã®ãªãã·ã§ã³ã¯ãã³ãŒãã®èªåçæã䜿çšããããšã§ãã
ãã®èšäºã§ã¯ã次ã®ããšã説æããŸãã
- Pythonããã³Jinjaã©ã€ãã©ãªã䜿çšããã³ãŒãèªåçæã䜿çšããASIC / FPGAã®éçºã§äœ¿çšãããVerilogèšèªã®å¶éã®1ã€ãåé¿ããæ¹æ³ã
- 説æããå¶åŸ¡ããã³ã¹ããŒã¿ã¹ã¬ãžã¹ã¿ã®ã¢ãžã¥ãŒã«ãçæããããšã«ãããIPã³ã¢ã®éçºãå éããæ¹æ³ã
èå³ãããã°ããã£ãããžããããïŒ
ã¢ãžã¥ãŒã«ã®ãã©ã¡ãŒã¿ãŒå
Verilog-2001èšèªã§éçºããŠãããåçŽãªãã«ããã¬ã¯ãµãäœæããå¿
èŠããããšæ³å®ããŠããŸãã
module simple_mux #( parameter D_WIDTH = 8 ) ( input [D_WIDTH-1:0] data_0_i, input [D_WIDTH-1:0] data_1_i, input sel_i, output [D_WIDTH-1:0] data_o ); assign data_o = ( sel_i ) ? ( data_1_i ): ( data_0_i ); endmodule
ããã§è€éãªããšã¯ãããŸããã
ãã ãã24/48ããŒãçšã®ããçš®ã®ã¹ã€ãããéçºããŠããå Žåãããæç¹ã§ãã±ããã¹ã€ããã³ã°ãè¡ãããã¢ãžã¥ãŒã«ãå¿
èŠã«ãªããŸãïŒããã«ã¯ãã«ãããŒããã«ããã¬ã¯ãµãå¿
èŠã§ãïŒã
æåã§è¡ãã«ã¯ïŒ
input [D_WIDTH-1:0] data_0_i, input [D_WIDTH-1:0] data_1_i, ... input [D_WIDTH-1:0] data_47_i,
ããŸãæ£ãããããŸããã å®éã«ã¯ãããŒã¿ã ãã§ãªããåããŒã¿ã¹ããªãŒã ïŒèªã¿åããããŒãïŒããšã«1ã€ã§ã¯ãªãè€æ°ã®ä¿¡å·ãååšããå°çšã®ã€ã³ã¿ãŒãã§ã€ã¹ãå¿
èŠã§ãã
éã¯ãã®ãããªããšãæžãããã«æ±ããŸãïŒ
module simple_mux #( parameter D_WIDTH = 8, parameter PORT_CNT = 48, // internal param parameter SEL_WIDTH = $clog2( PORT_CNT ) ) ( input [D_WIDTH-1:0] data_i [PORT_CNT-1:0], input [SEL_WIDTH-1:0] sel_i, output [D_WIDTH-1:0] data_o ); assign data_o = data_i[ sel_i ]; endmodule
ãã ããã¢ãžã¥ãŒã«ããŒãã§ã®ã¢ã¬ã€ã®äœ¿çšã¯ãIEEE 1364-2001æšæºïŒVerilog-2001ã«ã€ããŠèª¬æ
ãããŠ
ããŸãïŒ
ã§ã¯èš±å¯ãããŠ
ããŸãã ã
ãã®ãããããšãã°ã
Quartusã¯æ¬¡ã®ãšã©ãŒãçæããŸãã
Error (10773): Verilog HDL error: declaring module ports or function arguments with unpacked array types requires SystemVerilog extensions
ã©ãããïŒ
é衚瀺ã®ããã¹ãSystemVerilogã䜿çšããŸãã
é衚瀺ã®ããã¹ã:)
èããããåé¿çã®1ã€ã
StackOverflowã§æ€èšãããŠããŸãã ã¢ã€ãã¢ã¯æ©èœããŠããŸãããèšäºã¯ããã«ã€ããŠã§ã¯ãããŸãã:)
ãã¡ããããã³ãã«ããããããŠå¿
èŠãªã¯ã€ã€ãäœãããšãã§ããŸããããã·ã³ããããè¡ãæ¹ãè¯ãã§ãïŒ
Jinja2ãã³ãã¬ãŒããšã³ãžã³ã®
Templateã¯ã©ã¹ã䜿çšããŸã
t = Template(u""" module {{name}} #( parameter D_WIDTH = 8 ) ( {%- for p in ports %} input [D_WIDTH-1:0] data_{{p}}_i, {%- endfor %} input [{{sel_width-1}}:0] sel_i, output [D_WIDTH-1:0] data_o ); always @(*) begin case( sel_i ) {% for p in ports %} {{sel_width}}'d{{p}}: begin data_o = data_{{p}}_i; end {% endfor %} endcase end endmodule """) print t.render( n = 4, sel_width = 2, name = "simple_mux_4habr", ports = range( 4 ) )
ã¢ãžã¥ãŒã«ãã³ãã¬ãŒããäœæããè€è£œã«å¿
èŠãªãã®
ã説æãã
ããã«äœ¿çš
ã ãå¿
èŠãªãã©ã¡ãŒã¿ãŒïŒããŒãã®æ°ãã¢ãžã¥ãŒã«åãªã©ïŒãæž¡ããŠ
renderããã«ããŸããã
{{}}ã䜿çšãããããã®ãã©ã¡ãŒã¿ãŒã¯ãã³ãã¬ãŒãã§äœ¿çšã§ããç®çã®å Žæã«å€æ°ãæ¿å
¥ã§ããŸãã
åºåã¯çŽ æŽãããã¢ãžã¥ãŒã«ã§ããïŒ
é衚瀺ã®ããã¹ã module simple_mux_4habr #( parameter D_WIDTH = 8 ) ( input [D_WIDTH-1:0] data_0_i, input [D_WIDTH-1:0] data_1_i, input [D_WIDTH-1:0] data_2_i, input [D_WIDTH-1:0] data_3_i, input [1:0] sel_i, output [D_WIDTH-1:0] data_o ); always @(*) begin case( sel_i ) 2'd0: begin data_o = data_0_i; end 2'd1: begin data_o = data_1_i; end 2'd2: begin data_o = data_2_i; end 2'd3: begin data_o = data_3_i; end endcase end endmodule
çŸããã¯ãå€æ°ãšããŠæž¡ãããšãã§ããã®ã¯æ°åãæååã ãã§ãªããPythonã¿ã€ãïŒã·ãŒããèŸæžãã¯ã©ã¹ã®ãªããžã§ã¯ãïŒã§ãããPythonã³ãŒããšåãæ¹æ³ã§ãã³ãã¬ãŒãã«ã¢ã¯ã»ã¹ã§ããããšã§ãã ããšãã°ãèŸæžèŠçŽ ã®åŒã³åºãã¯æ¬¡ã®ããã«ãªããŸãã
{{ foo['bar'] }}
ãã¡ãããããã¯åçŽãªäŸã§ãããããããperl / sed / awkãªã©ã䜿çšããŠå®è¡ã§ããŸãã
Jinjaã«ã€ããŠèªãã§ãç°¡åãªäŸã§éãã§ã¿ããšãããã£ãšæ·±å»ãªããšã«äœ¿çšã§ããã®ã§ã¯ãªãããšæããŸããã FPGAã®éçºã§çºçãã1ã€ã®åé¡ãæãåºããŸããããããã¯ååã«èªååãããŠããããã§ãã ãã®ã¿ã¹ã¯ãã¹ã ãŒãºã«é²ããããã«ãéçºã®æ§æã«ã€ããŠå°ã説æããŸãã
IPã³ã¢
ASIC / FPGAã®è¿
éãªéçºã®åºç€ã¯ãIPã³ã¢ãšããŠèšèšãããæ¢è£œã®ã³ãŒãã®äœ¿çšã§ãããšèããããŠããŸãã 詳现ã«å
¥ãããšãªããIPã³ã¢ã¯ã©ã€ãã©ãªã§ãããšæ³å®ã§ããŸãã
ã¢ã€ãã¢ã¯ããã¹ãŠã®ãã¡ãŒã ãŠã§ã¢ãIPã³ã¢ã«åå²ããããããèªåã§æžã蟌ãŸãããã賌å
¥ãããŠ
çãŸãããã
ã¯ã©ãã¯ãããããæšæºã€ã³ã¿ãŒãã§ã€ã¹ïŒAXIãAvalonãªã©ïŒã䜿çšããŠæ¥ç¶ãããããšã§ãã æ¥ç¶ã¯ããã³ãã«ãŸãã¯GUIã¢ããªã±ãŒã·ã§ã³ã®å©ããåããŠè¡ãããšãã§ããŸããGUIã¢ããªã±ãŒã·ã§ã³ã§ã¯ãå¿
èŠãªã«ãŒãã«ãã¯ãªãã¯ããŠããŠã¹ã§æ¥ç¶ã§ããŸãã ããšãã°ã
Quartusã«ä»å±ãã
Qsysã§ãã
ãã®ã¢ãããŒãã®å©ç¹ã¯æããã§ãã
- æºåãã§ããã³ãŒãæ¹èš
- åå¥ã®ã³ã¢ãã¹ã
- ã¢ãžã¥ãŒã«éã®ããŒã¿äº€æã®æšæºå
ãã€ãã¹é¢ã®1ã€ã¯ãæšæºã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠæ¥ç¶ããããã®ãªãŒããŒãããããããšããäºå®ã§ããããã¯ãããå€ãã®ã³ãŒããŸãã¯ããå€ãã®ãªãœãŒã¹ïŒã»ã«ïŒãå æããå¯èœæ§ããããŸãã
åã³ã¢ã«ã¯ã
CSRã¹ããŒã¿ã¹ã¬ãžã¹ã¿ã®ã»ããããããŸãã
ã»ãšãã©ã®å Žåããããã¯åèªïŒããšãã°32ãããïŒã«åŸã£ãŠã°ã«ãŒãåãããå
éšã§ã¯ãã£ãŒã«ãã«ãã£ãŠåå²ãããŸãããã£ãŒã«ãã¯ç°ãªãåäœã¢ãŒããæã€ããšãã§ããŸãã
- RW-èªã¿åããšæžã蟌ã¿ïŒæžã蟌ã¿ãšèªã¿åããã§ããŸãã ãããã¯ãã«ãŒãã«ãæ§æããããã«äœ¿çšãããŸãïŒããšãã°ãç¹å®ã®æäœã¢ãŒãã®çµã¿èŸŒã¿ãããã€ãã®ãã©ã¡ãŒã¿ãŒã®èšå®ãªã©ïŒã
- RW / SC-èªã¿åãæžã蟌ã¿èªå·±ã¯ãªã¢ïŒãŠããããæžã蟌ããšããŠãããèªäœããŒãã«ãªã»ãããããŸãïŒã«ãŒãã«ãŸãã¯ã«ãŒãã«ã¢ãžã¥ãŒã«ã®ãªã»ããã«äŸ¿å©ãªå ŽåããããŸãïŒãŠãããã眮ããšãããèªäœããŒãã«ãªã»ãããããŸãïŒã
- RO-èªã¿åãå°çšïŒèªã¿åãå°çšïŒããšãã°ãçµ±èšãŸãã¯ã«ãŒãã«ã®ç¶æ
ã«ã€ããŠïŒã ãŸããå®æ°å€ïŒã«ãŒãã«ããŒãžã§ã³ããã®æ©èœãªã©ïŒãæ ŒçŽããããã«ROã«ãã£ãŠäœæãããã¬ãžã¹ã¿ããããŸãã
- RO / LLããã³RO / LH-èªã¿åãå°çšã©ããããŒ/ã©ãããã€ïŒå¥ã®ããªãããŒãªã¬ãžã¹ã¿-ã¯ã©ãã·ã¥ã远跡ããããã«äœ¿çšã§ããŸããããšãã°ãROã¬ãžã¹ã¿ã«çœ®ãã ãã§ãå°ããªãã®ã®ãªãŒããŒãããŒïŒ ãã«ã·ã°ãã«ã1ã«ãªã£ãïŒãçºçããå Žåããããã®ã¬ãžã¹ã¿ãèªã¿åãCPUã¯ããã®ã€ãã³ããã¹ãããã§ããŸãã ããã¯ã»ãã®æ°åã®æªçœ®ã§çºçããå¯èœæ§ããããŸãã ãã ããLHãå®è¡ãããšããŠãããããããšããã«ã¯ãªãã¯ãã次ã®èªã¿åããåŸ
æ©ããŸãã ãã®ã¬ãžã¹ã¿ãèªã¿åãããå Žåãã¬ãžã¹ã¿å€ã¯èªåçã«ãŒãã«ãªã»ãããããŸãã
åãã¬ãžã¹ã¿å
ã«ã¯ããã€ãã®ãã£ãŒã«ããããããããã®åäœã¢ãŒãã¯ç°ãªãå ŽåããããŸãã
åçŽãªI2Cãšã¯ã¹ãã³ããŒãããã©ã³ã·ãŒããŒãããã«ã¯ãããã¯ãŒã¯ã«ãŒãã«è³ããŸã§ãããŸããŸãªãããã®CSRããããŸãã
ãããã¬ãã«ã®ããã°ã©ããŒã¯ã©ã®ããã«èŠããŸããïŒ
ã¢ã«ãã©ã®
ããªãã«ã¹ããŒãã€ãŒãµããã MACã³ã³ãããŒã©ãæ€èšããŠãã ããã
ããã¥ã¡ã³ããéããŠ
ã æ§æã¬ãžã¹ã¿ç©ºé ãã®ç« ã«é²ããšãã«ãŒãã«ãå¶åŸ¡ãããã®ç¶æ
ã«é¢ããæ
å ±ïŒåä¿¡/éä¿¡ãã±ããã®ã«ãŠã³ã¿ãŒãªã©ïŒãåä¿¡ã§ãããã¹ãŠã®ã¬ãžã¹ã¿ã®ãªã¹ãã衚瀺ãããŸãã
ã¬ãžã¹ã¿ã説æãããŠããè¡šã®äžéšã瀺ããŸãã

ãšããã§ããããã®è¡ãèªã¿åããããã±ããããã®IPã³ã¢ãééããå¯èœæ§ããããŸãã
ããšãã°ããã®ã«ãŒãã«ã®ã¬ãžã¹ã¿0x03ããã³0x04ã¯ãMACã¢ãã¬ã¹ã®èšå®ãæ
åœããŸãã äžéšã®ã«ãŒãã«ïŒã¶ã€ãªã³ã¯ã¹ãŸãã¯Intel補ïŒã§ã¯ãä»ã®ã¬ãžã¹ã¿ã䜿çšã§ããŸãã
ãã©ã€ãã® MACã¢ãã¬ã¹ã®å€æŽã¯æ¬¡ã®ãšãã
ã§ã ã
static void tse_update_mac_addr(struct altera_tse_private *priv, u8 *addr) { u32 msb; u32 lsb; msb = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; lsb = ((addr[5] << 8) | addr[4]) & 0xffff; csrwr32(msb, priv->mac_dev, tse_csroffs(mac_addr_0)); csrwr32(lsb, priv->mac_dev, tse_csroffs(mac_addr_1)); }
mac_addr_0ãš
mac_addr_1ã¯0x03ãš0x04ã«ãããããããã¯éåžžã«ããªãããŒã§ãïŒç§ã®äž»èŠ³çãªæèŠã§ã¯ããã©ã€ããŒã§ã¯ãããæ£åžžã§ãããšæ³å®ããŠããŸãïŒããé£æ¥ãã
ããããŒãã¡ã€ã«ã§å®çŸ©ãããŠã
ãŸã ã
IPã³ã¢ã®éçºè
ã¯ããã¹ãŠã®CSRã説æããããã¥ã¡ã³ããæäŸããåæ§ã«ãäœããã©ã®ããã«ãã©ã®é åºã§æ§æãããã説æããŸãã ãã®ããã¥ã¡ã³ãã¯é«ã¬ãã«ã®ããã°ã©ããŒã«æž¡ããã
tse_update_mac_addrã«äŒŒã
é¢æ°ãäœæãããã¹ãŠæ©èœããããã«ããŸã:)
ãã«ãã³ã¢ã·ã¹ãã
å€ãã®å Žåã1ã€ã®ã³ã¢ã«ãã£ãŠããããããã¿ã¹ã¯ã¯è§£æ±ºã§ããŸãããã·ã¹ãã ã«ã¯ãããã®ããã€ãããããŸãã
管çã€ã³ã¿ãŒãã§ã€ã¹ã1ã€ã®ãã¹ã«æ¥ç¶ããŠãåã³ã¢ã«ç¬èªã®ã¢ãã¬ã¹ã¹ããŒã¹ãå²ãåœãŠãããšãã§ããŸãã
- IPã³ã¢AïŒ0x0000-0x00FF
- IPã³ã¢BïŒ0x0100-0x01FF
- IPã³ã¢CïŒ0x0200-0x02FF
äžäœã¬ãã«ãã«ãŒãã«Bã¬ãžã¹ã¿ã0x03ã«æžã蟌ãå¿
èŠãããå Žåãã¢ãã¬ã¹0x0103ã§ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããå¿
èŠããããŸãã ïŒç°¡åã«ããããã«ãã¢ãã¬ã¹ã¯ãã€ãã§ã¯ãªããåèªã«åŸã£ãŠãããšèããŠããŸããå®éã«ã¯ããã€ãã¢ãã¬ã¹ã§æžã蟌ãå¿
èŠãããããšãå€æããå ŽåããããŸãããã®åŸã32ãããã¬ãžã¹ã¿ã®ãªã¯ãšã¹ãã¯0x010Cã®ãã©ã³ã¶ã¯ã·ã§ã³ã«ãªããŸãïŒã

ãã¹ã¿ãŒïŒCPUïŒARM / x86ïŒãŸãã¯MCUããŸãã¯ä»ã®äžè¬çãªIPã³ã¢ïŒã¯ã管çã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠãèªã¿åããŸãã¯æžã蟌ã¿ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããŸãã IPã³ã¢ç®¡çã€ã³ã¿ãŒãã§ã€ã¹ã¯ãå€ãã®å ŽåãæšæºïŒAXIãŸãã¯AvalonïŒã®ããããã«åŸã£ãŠè¡ãããŸãã
è€æ°ã®ã¹ã¬ãŒããããå Žåãã€ã³ã¿ãŒã³ãã¯ãã¢ãžã¥ãŒã«ïŒãã«ããã¬ã¯ãµãŸãã¯ãã¹ã¢ãŒãã¿ãŒïŒã衚瀺ãããŸãã ãã®ã¿ã¹ã¯ã¯ããã¹ã¿ãŒããã®ãªã¯ãšã¹ããåãå
¥ãããã®ãªã¯ãšã¹ãã®éä¿¡å
ã確èªããããšã§ããããã¯ãã¹ã¬ãŒããå¿çããŠããéãªã©ã«ãã¹ãä¿æã§ãããªã©ã®æ¹æ³ã§ãã ãããã£ãŠããã®ã¢ãžã¥ãŒã«ã®åã¯ããªã¯ãšã¹ãã¢ãã¬ã¹ã¯0x0103ã§ãããããã®åŸã¯-0x0003ã§ããã IPã³ã¢ã¯ãã©ã®ã¢ãã¬ã¹ã¹ããŒã¹ãå²ãåœãŠãããŠããããèªèããŠããŸããïŒèªèãã¹ãã§ã¯ãªãïŒã
ç¹å®ã®IPã³ã¢ãå解ããŸãïŒåé¡ã瀺ããŸãïŒ
IPã³ã¢ã®å
éšã«ã¯ãããããã¹ãŠã®ã¬ãžã¹ã¿ãå«ãã¢ãžã¥ãŒã«ããããããããIPã³ã¢ã®å
éšã«ãããå€éšããã¯èŠããªãã¢ãžã¥ãŒã«ãå¶åŸ¡ããããã®ä¿¡å·ã»ããã«å€æããå¿
èŠããããŸãã
æã§è©±ããªãããã«ããããã«ãã€ãŒãµããããã±ãããžã§ãã¬ãŒã¿ãŒã®éåžžã«åçŽãªæœè±¡çãªIPã³ã¢ãæ€èšããŸããããã¯ãããšãã°
æž¬å® æ©åšã§äœ¿çšã§ããŸãã
ãã®ã«ãŒãã«ã«ãããã®ã¬ãžã¹ã¿ãæãããŠãã ããïŒ
0x0: [7:0] - IP_CORE_VERSION [RO] - IP- [15:8] - Reserved [16] - GEN_EN [RW] - [17] - GEN_ERROR [ROLH] - [30:18] - Reserved [31] - GEN_RESET [RWSC] - 0x1: [31:0] - IP_DST [RW] - IP- 0x2: [15:0] - FRM_SIZE [RW] - [31:16] - Reserved 0x3: [31:0] - FRM_CNT [RO] -
IPã³ã¢èªäœã¯æ¬¡ã®ããã«ãªããŸãã
csr_mapã¢ãžã¥ãŒã«ã¯ãæšæºã€ã³ã¿ãŒãã§ã€ã¹ããäž»èŠãªã«ãŒãã«æ©èœãå®è¡ãã
traffic_generatorã¢ãžã¥ãŒã«ã®å¶åŸ¡ä¿¡å·ã®ã»ããã«ãå€æããã圹å²ãæãããŸãã ãã¡ãããIPã³ã¢ã2ã€ã®ã¢ãžã¥ãŒã«ã®ã¿ã§æ§æãããããšã¯ã»ãšãã©ãããŸãããã»ãšãã©ã®å Žåãå¶åŸ¡ä¿¡å·ã¯IPã³ã¢å
ã®è€æ°ã®ã¢ãžã¥ãŒã«ã«é
ä¿¡ãããŸãã
ç§ãäœãåŸãŠããããæšæž¬ããŠãã ããïŒ
ãããã®ã¬ãžã¹ã¿ã®èª¬æãããã®csr_mapãèªåçã«çæããããšã¯å¯èœã§ããïŒ
å®éã«ã¯ãçŽ100ã®ã¬ãžã¹ã¿ãååšããå¯èœæ§ãããããããèªååãããŠããå Žåã¯ã次ã®ããã«ãªããŸãã
- ééããé¢çœããªãäœæ¥ãé¿ããããšãã§ããŸãã
- ã³ãŒãã®è¡ã®æ¯æãããããšã管çè
ããããŒãã¹ãåãåããŸãïŒå€ãã®å Žåãèªåçæã³ãŒãã«ã¯å€ãã®è¡ãå¿
èŠã§ãïŒã
- HabrïŒãŸãããŸãã¯giktaymsaãFPGAãããããã«ç§»åãããã>> _ïŒãŸãã¯ããã«ãŒã®ã²ãŒã ãèªãã®ã«æéãè²»ãããŸããã
åé¡ã解決ãã
ã¬ãžã¹ã¿ãšãããïŒãã£ãŒã«ãïŒã«ãã£ãŠæ
å ±ãæ ŒçŽããããã®2ã€ã®ããªããã£ãã¯ã©ã¹ãäœæããŸãã
class Reg( ): def __init__( self, num, name ): self.num = '{:X}'.format( num ) self.name = name self.name_lowcase = self.name.lower() self.bits = [] def add_bits( self, reg_bits ): self.bits.append( reg_bits ) class RegBits( ): def __init__( self, bit_msb, bit_lsb, name, mode = "RW", init_value = 0 ): self.bit_msb = bit_msb self.bit_lsb = bit_lsb self.width = bit_msb - bit_lsb + 1 self.name = name self.name_lowcase = self.name.lower() self.mode = mode self.init_value = '{:X}'.format( init_value )
ãããã®ã¯ã©ã¹ã䜿çšããŠãCSRèšè¿°ãäœæããŸãã
MODULE_NAME = "trafgen_map_4habr" r0 = Reg( 0x0, "MAIN") r0.add_bits( RegBits( 7, 0, "IP_CORE_VERSION", "RO_CONST", 0x7 ) ) r0.add_bits( RegBits( 16, 16, "GEN_EN" , "RW" ) ) r0.add_bits( RegBits( 17, 17, "GEN_ERROR", "RO_LH" ) ) r0.add_bits( RegBits( 31, 31, "GEN_RESET", "RW_SC" ) ) r1 = Reg( 0x1, "IP_DST" )
ãã³ãã¬ãŒãèªäœã¯æ¬¡ã®ããã«ãªããŸãã
é衚瀺ã®ããã¹ã csr_map_template = Template(u""" {%- macro reg_name( r ) -%} reg_{{r.num}}_{{r.name_lowcase}} {%- endmacro %} {%- macro reg_name_bits( r, b ) -%} reg_{{r.num}}_{{r.name_lowcase}}___{{b.name_lowcase}} {%- endmacro %} {%- macro bit_init_value( b ) -%} {{b.width}}'h{{b.init_value}} {%- endmacro %} {%- macro signal( width ) -%} [{{width-1}}:0] {%- endmacro %} {%- macro print_port_signal( dir, width, name, eol="," ) -%} {{ " %-12s %-10s %-10s" | format( dir, signal( width ), name+eol ) }} {%- endmacro %} {%- macro get_port_name( b ) -%} {%- if b.port_signal_input -%} {{b.name_lowcase}}_i {%- else -%} {{b.name_lowcase}}_o {%- endif -%} {%- endmacro -%} // Generated using CSR map generator // https://github.com/johan92/csr-map-generator module {{module_name}}( {%- for p in data %} // Register {{p.name}} signals {%- for b in p.bits %} {%- if b.port_signal_input %} {{print_port_signal( "input", b.width, get_port_name( b ) )}} {%- elif b.port_signal_output %} {{print_port_signal( "output", b.width, get_port_name( b ) )}} {%- endif %} {%- endfor %} {% endfor %} // CSR interface {{print_port_signal( "input", 1, "reg_clk_i" ) }} {{print_port_signal( "input", 1, "reg_rst_i" ) }} {{print_port_signal( "input", reg_d_w, "reg_wr_data_i" ) }} {{print_port_signal( "input", 1, "reg_wr_en_i" ) }} {{print_port_signal( "input", 1, "reg_rd_en_i" ) }} {{print_port_signal( "input", reg_a_w, "reg_addr_i" ) }} {{print_port_signal( "output", reg_d_w, "reg_rd_data_o", "" ) }} ); {%- for p in data %} // ****************************************** // Register {{p.name}} // ****************************************** logic [{{reg_d_w-1}}:0] {{reg_name( p )}}_read; {%- for b in p.bits %} {%- if b.mode != "RO" %} logic [{{b.width-1}}:0] {{reg_name_bits( p, b )}} = {{bit_init_value( b )}}; {%- endif %} {%- endfor %} {% for b in p.bits %} {%- if b.port_signal_output %} always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) {{reg_name_bits( p, b )}} <= {{bit_init_value( b )}}; else if( reg_wr_en_i && ( reg_addr_i == {{reg_a_w}}'h{{p.num}} ) ) {{reg_name_bits( p, b )}} <= reg_wr_data_i[{{b.bit_msb}}:{{b.bit_lsb}}]; {%-if b.mode == "RW_SC" %} else {{reg_name_bits( p, b )}} <= {{bit_init_value( b )}}; {% endif %} {%- endif %} {%- if b.mode == "RO_LH" or b.mode == "RO_LL" %} always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) {{reg_name_bits( p, b )}} <= {{bit_init_value( b )}}; else begin if( reg_rd_en_i && ( reg_addr_i == {{reg_a_w}}'h{{p.num}} ) ) {{reg_name_bits( p, b )}} <= {{bit_init_value( b )}}; {% if b.mode == "RO_LL" %} if( {{get_port_name( b )}} == 1'b0 ) {{reg_name_bits( p, b )}} <= 1'b0; {%- elif b.mode == "RO_LH" %} if( {{get_port_name( b )}} == 1'b1 ) {{reg_name_bits( p, b )}} <= 1'b1; {%- endif %} end {% endif %} {% endfor %} // assigning to output {%- for b in p.bits %} {%- if b.port_signal_output %} assign {{get_port_name( b )}} = {{reg_name_bits( p, b )}}; {%- endif %} {%- endfor %} {%- macro print_in_always_comb( r, b, _right_value ) -%} {%- if b == "" -%} {{ " %s%-7s = %s;" | format( reg_name( r ) + "_read", "", _right_value ) }} {%- else -%} {{ " %s%-7s = %s;" | format( reg_name( r ) + "_read", "["+b.bit_msb|string+":"+b.bit_lsb|string+"]" , _right_value ) }} {%- endif -%} {%- endmacro %} // assigning to read data always_comb begin {{print_in_always_comb( p, "", reg_d_w|string+"'h0" ) }} {%- for b in p.bits %} {%- if b.mode == "RO" %} {{print_in_always_comb( p, b, get_port_name( b ) )}} {%- else %} {{print_in_always_comb( p, b, reg_name_bits( p, b ) )}} {%- endif %} {%- endfor %} end {%- endfor %} // ****************************************** // Reading stuff // ****************************************** logic [{{reg_d_w-1}}:0] reg_rd_data = {{reg_d_w}}'h0; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_rd_data <= {{reg_d_w}}'h0; else if( reg_rd_en_i ) begin case( reg_addr_i ) {% for p in data %} {{reg_a_w}}'h{{p.num}}: begin reg_rd_data <= {{reg_name( p )}}_read; end {% endfor %} default: begin reg_rd_data <= {{reg_d_w}}'h0; end endcase end assign reg_rd_data_o = reg_rd_data; endmodule """)
ãã³ãã¬ãŒãçæãåŒãåºããŸãïŒ
res = csr_map_template.render( module_name = MODULE_NAME, reg_d_w = 32, reg_a_w = 8, data = reg_l )
ãã®ãããªã¢ãžã¥ãŒã«ããããŸãïŒ
é衚瀺ã®ããã¹ã // Generated using CSR map generator // https://github.com/johan92/csr-map-generator module trafgen_map_4habr( // Register MAIN signals output [0:0] gen_en_o, input [0:0] gen_error_i, output [0:0] gen_reset_o, // Register IP_DST signals output [31:0] ip_dst_o, // Register FRM_SIZE signals output [15:0] frm_size_o, // Register FRM_CNT signals input [31:0] frm_cnt_i, // CSR interface input [0:0] reg_clk_i, input [0:0] reg_rst_i, input [31:0] reg_wr_data_i, input [0:0] reg_wr_en_i, input [0:0] reg_rd_en_i, input [7:0] reg_addr_i, output [31:0] reg_rd_data_o ); // ****************************************** // Register MAIN // ****************************************** logic [31:0] reg_0_main_read; logic [7:0] reg_0_main___ip_core_version = 8'h7; logic [0:0] reg_0_main___gen_en = 1'h0; logic [0:0] reg_0_main___gen_error = 1'h0; logic [0:0] reg_0_main___gen_reset = 1'h0; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_0_main___gen_en <= 1'h0; else if( reg_wr_en_i && ( reg_addr_i == 8'h0 ) ) reg_0_main___gen_en <= reg_wr_data_i[16:16]; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_0_main___gen_error <= 1'h0; else begin if( reg_rd_en_i && ( reg_addr_i == 8'h0 ) ) reg_0_main___gen_error <= 1'h0; if( gen_error_i == 1'b1 ) reg_0_main___gen_error <= 1'b1; end always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_0_main___gen_reset <= 1'h0; else if( reg_wr_en_i && ( reg_addr_i == 8'h0 ) ) reg_0_main___gen_reset <= reg_wr_data_i[31:31]; else reg_0_main___gen_reset <= 1'h0; // assigning to output assign gen_en_o = reg_0_main___gen_en; assign gen_reset_o = reg_0_main___gen_reset; // assigning to read data always_comb begin reg_0_main_read = 32'h0; reg_0_main_read[7:0] = reg_0_main___ip_core_version; reg_0_main_read[16:16] = reg_0_main___gen_en; reg_0_main_read[17:17] = reg_0_main___gen_error; reg_0_main_read[31:31] = reg_0_main___gen_reset; end // ****************************************** // Register IP_DST // ****************************************** logic [31:0] reg_1_ip_dst_read; logic [31:0] reg_1_ip_dst___ip_dst = 32'hB2F8E921; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_1_ip_dst___ip_dst <= 32'hB2F8E921; else if( reg_wr_en_i && ( reg_addr_i == 8'h1 ) ) reg_1_ip_dst___ip_dst <= reg_wr_data_i[31:0]; // assigning to output assign ip_dst_o = reg_1_ip_dst___ip_dst; // assigning to read data always_comb begin reg_1_ip_dst_read = 32'h0; reg_1_ip_dst_read[31:0] = reg_1_ip_dst___ip_dst; end // ****************************************** // Register FRM_SIZE // ****************************************** logic [31:0] reg_2_frm_size_read; logic [15:0] reg_2_frm_size___frm_size = 16'h40; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_2_frm_size___frm_size <= 16'h40; else if( reg_wr_en_i && ( reg_addr_i == 8'h2 ) ) reg_2_frm_size___frm_size <= reg_wr_data_i[15:0]; // assigning to output assign frm_size_o = reg_2_frm_size___frm_size; // assigning to read data always_comb begin reg_2_frm_size_read = 32'h0; reg_2_frm_size_read[15:0] = reg_2_frm_size___frm_size; end // ****************************************** // Register FRM_CNT // ****************************************** logic [31:0] reg_3_frm_cnt_read; // assigning to output // assigning to read data always_comb begin reg_3_frm_cnt_read = 32'h0; reg_3_frm_cnt_read[31:0] = frm_cnt_i; end // ****************************************** // Reading stuff // ****************************************** logic [31:0] reg_rd_data = 32'h0; always_ff @( posedge reg_clk_i or posedge reg_rst_i ) if( reg_rst_i ) reg_rd_data <= 32'h0; else if( reg_rd_en_i ) begin case( reg_addr_i ) 8'h0: begin reg_rd_data <= reg_0_main_read; end 8'h1: begin reg_rd_data <= reg_1_ip_dst_read; end 8'h2: begin reg_rd_data <= reg_2_frm_size_read; end 8'h3: begin reg_rd_data <= reg_3_frm_cnt_read; end default: begin reg_rd_data <= 32'h0; end endcase end assign reg_rd_data_o = reg_rd_data; endmodule
ã芧ã®ããã«ãã¢ã€ãã¢ã¯ããŸããããŸããïŒç°¡åãªããã¹ãã®èª¬æããæ¬æ Œçãªã¢ãžã¥ãŒã«ãç»å ŽããŸãããæäœæ¥ã§ä»äžããå¿
èŠã¯ãããŸãã-ããã«çç£ã«ç§»ãããšãã§ããŸãïŒ
管çã€ã³ã¿ãŒãã§ãŒã¹ãšããŠãé¡äŒŒæ§
Avalon-MMã䜿çšãããŸãã ã
ãŸãšã
ã»ãã®æ°æ¥åã«ãGinhubã§
å®è£
ããã 1Gããã³10G MACã³ã¢ãšUDP / IPã¹ã¿ãã¯ãèŠããšãã«ã
Jinja2ã«åºäŒããŸããã ã¡ãªã¿ã«ãããã¯ããŸãæžãããŠããŸããããç§ã¯ããªãè¡šé¢çã«ãã·ãã¥ã¬ãŒã·ã§ã³ã§èŠããŸããã
èè
ã¯ãJinja2ã䜿çšããŠãããšãã°
NããŒããã«ããã¬ã¯ãµãŒAXI4-Streamãªã©ã®ããŸããŸãªã¢ãžã¥ãŒã«ãçæããŸãã ãã®ãã«ããã¬ã¯ãµã¯ããã®èšäºã®åé ã§æžãããã®ãããã¯ããã«è€éã§ãã
ç§ã¯
csr_mapãçæããããã®ã¹ã¯ãªãããæ¥ãã§æããŠã
Jinja2ã®æ©èœãæããŸããïŒãã ãããã®äžéšãæè¬ããŠãããšæããŸãïŒãã³ãŒãã
ãã¡ããããã®ã¹ã¯ãªããã¯æªå å·¥ã§ããããŸã éçºã«ã¯äœ¿çšããŠããŸããïŒããŸããŸãªçç±ã§IPã³ã¢ã®çŸããã¢ãŒããã¯ãã£ãçŸããã¢ãŒããã¯ãã£ã®ãŸãŸã§ããããšãããããã䜿çšãããã©ããããããããŸããïŒã
ãœãŒã¹ã³ãŒã
ãgithubã«å®å
šã«ã¢ããããŒãããŸããã ãã®ãã³ãã¬ãŒãã誰ãã«åœ¹ç«ã€å Žåãç§ã¯åãã§ããŸãïŒãªã¯ãšã¹ãã«å¿ããŠæ¹åãããã誰ãã®ãã«ãªã¯ãšã¹ããåãå
¥ããæºåãã§ããŠããŸãïŒ
ãæž
èŽããããšãããããŸããïŒ è³ªåãããå Žåã¯ãééããªã質åããŠãã ããã
é衚瀺ã®ããã¹ããã¡ãããFPGAãããæèšã«
移åãããããšã¯æ®å¿µã§ãã