rggen-vhdl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/LICENSE +21 -0
  4. data/README.md +74 -0
  5. data/lib/rggen/vhdl.rb +50 -0
  6. data/lib/rggen/vhdl/bit_field/type.rb +85 -0
  7. data/lib/rggen/vhdl/bit_field/type/rc_w0c_w1c_wc_woc.erb +27 -0
  8. data/lib/rggen/vhdl/bit_field/type/rc_w0c_w1c_wc_woc.rb +51 -0
  9. data/lib/rggen/vhdl/bit_field/type/ro.erb +24 -0
  10. data/lib/rggen/vhdl/bit_field/type/ro.rb +21 -0
  11. data/lib/rggen/vhdl/bit_field/type/rof.erb +24 -0
  12. data/lib/rggen/vhdl/bit_field/type/rof.rb +7 -0
  13. data/lib/rggen/vhdl/bit_field/type/rs_w0s_w1s_ws_wos.erb +27 -0
  14. data/lib/rggen/vhdl/bit_field/type/rs_w0s_w1s_ws_wos.rb +42 -0
  15. data/lib/rggen/vhdl/bit_field/type/rw_w1_wo_wo1.erb +26 -0
  16. data/lib/rggen/vhdl/bit_field/type/rw_w1_wo_wo1.rb +23 -0
  17. data/lib/rggen/vhdl/bit_field/type/rwc.erb +25 -0
  18. data/lib/rggen/vhdl/bit_field/type/rwc.rb +24 -0
  19. data/lib/rggen/vhdl/bit_field/type/rwe_rwl.erb +25 -0
  20. data/lib/rggen/vhdl/bit_field/type/rwe_rwl.rb +33 -0
  21. data/lib/rggen/vhdl/bit_field/type/rws.erb +24 -0
  22. data/lib/rggen/vhdl/bit_field/type/rws.rb +27 -0
  23. data/lib/rggen/vhdl/bit_field/type/w0crs_w0src_w1crs_w1src_wcrs_wsrc.erb +26 -0
  24. data/lib/rggen/vhdl/bit_field/type/w0crs_w0src_w1crs_w1src_wcrs_wsrc.rb +36 -0
  25. data/lib/rggen/vhdl/bit_field/type/w0t_w1t.erb +25 -0
  26. data/lib/rggen/vhdl/bit_field/type/w0t_w1t.rb +22 -0
  27. data/lib/rggen/vhdl/bit_field/type/w0trg_w1trg.erb +17 -0
  28. data/lib/rggen/vhdl/bit_field/type/w0trg_w1trg.rb +19 -0
  29. data/lib/rggen/vhdl/bit_field/type/wrc_wrs.erb +25 -0
  30. data/lib/rggen/vhdl/bit_field/type/wrc_wrs.rb +22 -0
  31. data/lib/rggen/vhdl/bit_field/vhdl_top.rb +93 -0
  32. data/lib/rggen/vhdl/component.rb +7 -0
  33. data/lib/rggen/vhdl/factories.rb +11 -0
  34. data/lib/rggen/vhdl/feature.rb +31 -0
  35. data/lib/rggen/vhdl/register/default.erb +29 -0
  36. data/lib/rggen/vhdl/register/type.rb +109 -0
  37. data/lib/rggen/vhdl/register/type/default.erb +31 -0
  38. data/lib/rggen/vhdl/register/type/external.erb +29 -0
  39. data/lib/rggen/vhdl/register/type/external.rb +44 -0
  40. data/lib/rggen/vhdl/register/type/indirect.erb +35 -0
  41. data/lib/rggen/vhdl/register/type/indirect.rb +34 -0
  42. data/lib/rggen/vhdl/register/vhdl_top.rb +40 -0
  43. data/lib/rggen/vhdl/register_block/protocol.rb +48 -0
  44. data/lib/rggen/vhdl/register_block/protocol/apb.erb +34 -0
  45. data/lib/rggen/vhdl/register_block/protocol/apb.rb +20 -0
  46. data/lib/rggen/vhdl/register_block/protocol/axi4lite.erb +49 -0
  47. data/lib/rggen/vhdl/register_block/protocol/axi4lite.rb +42 -0
  48. data/lib/rggen/vhdl/register_block/vhdl_top.erb +26 -0
  49. data/lib/rggen/vhdl/register_block/vhdl_top.rb +103 -0
  50. data/lib/rggen/vhdl/register_file/vhdl_top.rb +25 -0
  51. data/lib/rggen/vhdl/setup.rb +11 -0
  52. data/lib/rggen/vhdl/utility.rb +28 -0
  53. data/lib/rggen/vhdl/utility/data_object.rb +91 -0
  54. data/lib/rggen/vhdl/utility/identifier.rb +38 -0
  55. data/lib/rggen/vhdl/utility/local_scope.rb +66 -0
  56. data/lib/rggen/vhdl/version.rb +7 -0
  57. metadata +130 -0
@@ -0,0 +1,35 @@
1
+ <% index_fields_and_values.each_with_index do |(field, value), i| %>
2
+ <%= indirect_match[i] %> <= '1' when unsigned(<%= field %>) = <%= value %> else '0';
3
+ <% end %>
4
+ u_register: entity work.rggen_indirect_register
5
+ generic map (
6
+ READABLE => <%= readable? %>,
7
+ WRITABLE => <%= writable? %>,
8
+ ADDRESS_WIDTH => <%= address_width %>,
9
+ OFFSET_ADDRESS => <%= offset_address %>,
10
+ BUS_WIDTH => <%= bus_width %>,
11
+ DATA_WIDTH => <%= width %>,
12
+ VALID_BITS => <%= valid_bits %>,
13
+ INDIRECT_MATCH_WIDTH => <%= match_width %>
14
+ )
15
+ port map (
16
+ i_clk => <%= clock %>,
17
+ i_rst_n => <%= reset %>,
18
+ i_register_valid => <%= register_valid %>,
19
+ i_register_access => <%= register_access %>,
20
+ i_register_address => <%= register_address %>,
21
+ i_register_write_data => <%= register_write_data %>,
22
+ i_register_strobe => <%= register_strobe %>,
23
+ o_register_active => <%= register_active %>,
24
+ o_register_ready => <%= register_ready %>,
25
+ o_register_status => <%= register_status %>,
26
+ o_register_read_data => <%= register_read_data %>,
27
+ o_register_value => <%= register_value %>,
28
+ i_indirect_match => <%= indirect_match %>,
29
+ o_bit_field_valid => <%= bit_field_valid %>,
30
+ o_bit_field_read_mask => <%= bit_field_read_mask %>,
31
+ o_bit_field_write_mask => <%= bit_field_write_mask %>,
32
+ o_bit_field_write_data => <%= bit_field_write_data %>,
33
+ i_bit_field_read_data => <%= bit_field_read_data %>,
34
+ i_bit_field_value => <%= bit_field_value %>
35
+ );
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_list_item_feature(:register, :type, :indirect) do
4
+ vhdl do
5
+ build do
6
+ signal :indirect_match, { width: match_width }
7
+ end
8
+
9
+ main_code :register, from_template: true
10
+
11
+ private
12
+
13
+ def match_width
14
+ register.index_entries.size
15
+ end
16
+
17
+ def index_fields
18
+ register
19
+ .collect_index_fields(register_block.bit_fields)
20
+ .map(&:value)
21
+ end
22
+
23
+ def index_values
24
+ loop_variables = register.local_loop_variables
25
+ register.index_entries.map do |entry|
26
+ entry.array_index? && loop_variables.shift || entry.value
27
+ end
28
+ end
29
+
30
+ def index_fields_and_values
31
+ index_fields.zip(index_values)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_simple_feature(:register, :vhdl_top) do
4
+ vhdl do
5
+ include RgGen::SystemVerilog::RTL::RegisterIndex
6
+
7
+ build do
8
+ unless register.bit_fields.empty?
9
+ signal :bit_field_valid
10
+ signal :bit_field_read_mask, width: register.width
11
+ signal :bit_field_write_mask, width: register.width
12
+ signal :bit_field_write_data, width: register.width
13
+ signal :bit_field_read_data, width: register.width
14
+ signal :bit_field_value, width: register.width
15
+ end
16
+ end
17
+
18
+ main_code :register_file do
19
+ local_scope("g_#{register.name}") do |scope|
20
+ scope.loop_size loop_size
21
+ scope.signals signals
22
+ scope.body(&method(:body_code))
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def loop_size
29
+ register.array? && local_loop_variables.zip(register.array_size) || nil
30
+ end
31
+
32
+ def signals
33
+ register.declarations[:signal]
34
+ end
35
+
36
+ def body_code(code)
37
+ register.generate_code(code, :register, :top_down)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_list_feature(:register_block, :protocol) do
4
+ vhdl do
5
+ shared_context.feature_registry(registry)
6
+
7
+ base_feature do
8
+ build do
9
+ generic :address_width, {
10
+ name: 'ADDRESS_WIDTH', type: :positive, default: local_address_width
11
+ }
12
+ generic :pre_decode, {
13
+ name: 'PRE_DECODE', type: :boolean, default: false
14
+ }
15
+ generic :base_address, {
16
+ name: 'BASE_ADDRESS', default: hex(0, 4)
17
+ }
18
+ generic :error_status, {
19
+ name: 'ERROR_STATUS', type: :boolean, default: false
20
+ }
21
+ end
22
+
23
+ private
24
+
25
+ def bus_width
26
+ configuration.bus_width
27
+ end
28
+
29
+ def local_address_width
30
+ register_block.local_address_width
31
+ end
32
+
33
+ def total_registers
34
+ register_block.files_and_registers.sum(&:count)
35
+ end
36
+
37
+ def byte_size
38
+ register_block.byte_size
39
+ end
40
+ end
41
+
42
+ factory do
43
+ def target_feature_key(configuration, _register_block)
44
+ configuration.protocol
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,34 @@
1
+ u_adapter: entity work.rggen_apb_adaper
2
+ generic map (
3
+ ADDRESS_WIDTH => <%= address_width %>,
4
+ LOCAL_ADDRESS_WIDTH => <%= local_address_width %>,
5
+ BUS_WIDTH => <%= bus_width %>,
6
+ REGISTERS => <%= total_registers %>,
7
+ PRE_DECODE => <%= pre_decode %>,
8
+ BASE_ADDRESS => <%= base_address %>,
9
+ BYTE_SIZE => <%= byte_size %>,
10
+ ERROR_STATUS => <%= error_status %>
11
+ )
12
+ port map (
13
+ i_clk => <%= register_block.clock %>,
14
+ i_rst_n => <%= register_block.reset %>,
15
+ i_psel => <%= psel %>,
16
+ i_penable => <%= penable %>,
17
+ i_paddr => <%= paddr %>,
18
+ i_pprot => <%= pprot %>,
19
+ i_pwrite => <%= pwrite %>,
20
+ i_pstrb => <%= pstrb %>,
21
+ i_pwdata => <%= pwdata %>,
22
+ o_pready => <%= pready %>,
23
+ o_prdata => <%= prdata %>,
24
+ o_pslverr => <%= pslverr %>,
25
+ o_register_valid => <%= register_block.register_valid %>,
26
+ o_register_access => <%= register_block.register_access %>,
27
+ o_register_address => <%= register_block.register_address %>,
28
+ o_register_write_data => <%= register_block.register_write_data %>,
29
+ o_register_strobe => <%= register_block.register_strobe %>,
30
+ i_register_active => <%= register_block.register_active %>,
31
+ i_register_ready => <%= register_block.register_ready %>,
32
+ i_register_status => <%= register_block.register_status %>,
33
+ i_register_read_data => <%= register_block.register_read_data %>
34
+ );
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_list_item_feature(:register_block, :protocol, :apb) do
4
+ vhdl do
5
+ build do
6
+ input :psel, { name: 'i_psel' }
7
+ input :penable, { name: 'i_penable' }
8
+ input :paddr, { name: 'i_paddr', width: address_width }
9
+ input :pprot, { name: 'i_pprot', width: 3 }
10
+ input :pwrite, { name: 'i_pwrite' }
11
+ input :pstrb, { name: 'i_pstrb', width: bus_width / 8 }
12
+ input :pwdata, { name: 'i_pwdata', width: bus_width }
13
+ output :pready, { name: 'o_pready' }
14
+ output :prdata, { name: 'o_prdata', width: bus_width }
15
+ output :pslverr, { name: 'o_pslverr' }
16
+ end
17
+
18
+ main_code :register_block, from_template: true
19
+ end
20
+ end
@@ -0,0 +1,49 @@
1
+ u_adapter: entity work.rggen_axi4lite_adapter
2
+ generic map (
3
+ ID_WIDTH => <%= id_width %>,
4
+ ADDRESS_WIDTH => <%= address_width %>,
5
+ LOCAL_ADDRESS_WIDTH => <%= local_address_width %>,
6
+ BUS_WIDTH => <%= bus_width %>,
7
+ REGISTERS => <%= total_registers %>,
8
+ PRE_DECODE => <%= pre_decode %>,
9
+ BASE_ADDRESS => <%= base_address %>,
10
+ BYTE_SIZE => <%= byte_size %>,
11
+ ERROR_STATUS => <%= error_status %>,
12
+ WRITE_FIRST => <%= write_first %>
13
+ )
14
+ port map (
15
+ i_clk => <%= register_block.clock %>,
16
+ i_rst_n => <%= register_block.reset %>,
17
+ i_awvalid => <%= awvalid %>,
18
+ o_awready => <%= awready %>,
19
+ i_awid => <%= awid %>,
20
+ i_awaddr => <%= awaddr %>,
21
+ i_awprot => <%= awprot %>,
22
+ i_wvalid => <%= wvalid %>,
23
+ o_wready => <%= wready %>,
24
+ i_wdata => <%= wdata %>,
25
+ i_wstrb => <%= wstrb %>,
26
+ o_bvalid => <%= bvalid %>,
27
+ i_bready => <%= bready %>,
28
+ o_bid => <%= bid %>,
29
+ o_bresp => <%= bresp %>,
30
+ i_arvalid => <%= arvalid %>,
31
+ o_arready => <%= arready %>,
32
+ i_arid => <%= arid %>,
33
+ i_araddr => <%= araddr %>,
34
+ i_arprot => <%= arprot %>,
35
+ o_rvalid => <%= rvalid %>,
36
+ i_rready => <%= rready %>,
37
+ o_rid => <%= rid %>,
38
+ o_rdata => <%= rdata %>,
39
+ o_rresp => <%= rresp %>,
40
+ o_register_valid => <%= register_block.register_valid %>,
41
+ o_register_access => <%= register_block.register_access %>,
42
+ o_register_address => <%= register_block.register_address %>,
43
+ o_register_write_data => <%= register_block.register_write_data %>,
44
+ o_register_strobe => <%= register_block.register_strobe %>,
45
+ i_register_active => <%= register_block.register_active %>,
46
+ i_register_ready => <%= register_block.register_ready %>,
47
+ i_register_status => <%= register_block.register_status %>,
48
+ i_register_read_data => <%= register_block.register_read_data %>
49
+ );
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_list_item_feature(:register_block, :protocol, :axi4lite) do
4
+ vhdl do
5
+ build do
6
+ generic :id_width, { name: 'ID_WIDTH', type: :natural, default: 0 }
7
+ generic :write_first, { name: 'WRITE_FIRST', type: :boolean, default: true }
8
+
9
+ input :awvalid, { name: 'i_awvalid' }
10
+ output :awready, { name: 'o_awready' }
11
+ input :awid, { name: 'i_awid', width: id_width_value }
12
+ input :awaddr, { name: 'i_awaddr', width: address_width }
13
+ input :awprot, { name: 'i_awprot', width: 3 }
14
+ input :wvalid, { name: 'i_wvalid' }
15
+ output :wready, { name: 'o_wready' }
16
+ input :wdata, { name: 'i_wdata', width: bus_width }
17
+ input :wstrb, { name: 'i_wstrb', width: bus_width / 8 }
18
+ output :bvalid, { name: 'o_bvalid' }
19
+ input :bready, { name: 'i_bready' }
20
+ output :bid, { name: 'o_bid', width: id_width_value }
21
+ output :bresp, { name: 'o_bresp', width: 2 }
22
+ input :arvalid, { name: 'i_arvalid' }
23
+ output :arready, { name: 'o_arready' }
24
+ input :arid, { name: 'i_arid', width: id_width_value }
25
+ input :araddr, { name: 'i_araddr', width: address_width }
26
+ input :arprot, { name: 'i_arprot', width: 3 }
27
+ output :rvalid, { name: 'o_rvalid' }
28
+ input :rready, { name: 'i_rready' }
29
+ output :rid, { name: 'o_rid', width: id_width_value }
30
+ output :rdata, { name: 'o_rdata', width: bus_width }
31
+ output :rresp, { name: 'o_rresp', width: 2 }
32
+ end
33
+
34
+ main_code :register_block, from_template: true
35
+
36
+ private
37
+
38
+ def id_width_value
39
+ "clip_id_width(#{id_width})"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ library ieee;
2
+ use ieee.std_logic_1164.all;
3
+ use ieee.numeric_std.all;
4
+
5
+ use work.rggen_rtl.all;
6
+
7
+ entity <%= register_block.name %> is
8
+ generic (
9
+ <% generic_declarations.each do |declaration| %>
10
+ <%= declaration %>
11
+ <% end %>
12
+ );
13
+ port (
14
+ <% port_declarations.each do |declaration| %>
15
+ <%= declaration %>
16
+ <% end %>
17
+ );
18
+ end <%= register_block.name %>;
19
+
20
+ architecture rtl of <%= register_block.name %> is
21
+ <% signal_declarations.each do |declaration| %>
22
+ <%= declaration %>;
23
+ <% end %>
24
+ begin
25
+ <%= architecture_body_code.to_s.chomp %>
26
+ end rtl;
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ RgGen.define_simple_feature(:register_block, :vhdl_top) do
4
+ vhdl do
5
+ build do
6
+ input :clock, { name: 'i_clk' }
7
+ input :reset, { name: 'i_rst_n' }
8
+
9
+ signal :register_valid
10
+ signal :register_access, {
11
+ width: 2
12
+ }
13
+ signal :register_address, {
14
+ width: address_width
15
+ }
16
+ signal :register_write_data, {
17
+ width: bus_width
18
+ }
19
+ signal :register_strobe, {
20
+ width: bus_width / 8
21
+ }
22
+ signal :register_active, {
23
+ array_size: [total_registers]
24
+ }
25
+ signal :register_ready, {
26
+ array_size: [total_registers]
27
+ }
28
+ signal :register_status, {
29
+ width: 2, array_size: [total_registers]
30
+ }
31
+ signal :register_read_data, {
32
+ width: bus_width, array_size: [total_registers]
33
+ }
34
+ signal :register_value, {
35
+ width: value_width, array_size: [total_registers]
36
+ }
37
+ end
38
+
39
+ write_file '<%= register_block.name %>.vhd' do |file|
40
+ file.body { process_template }
41
+ end
42
+
43
+ private
44
+
45
+ def total_registers
46
+ register_block.files_and_registers.sum(&:count)
47
+ end
48
+
49
+ def address_width
50
+ register_block.local_address_width
51
+ end
52
+
53
+ def bus_width
54
+ configuration.bus_width
55
+ end
56
+
57
+ def value_width
58
+ register_block.registers.map(&:width).max
59
+ end
60
+
61
+ def generic_declarations
62
+ register_block
63
+ .declarations[:generic]
64
+ .yield_self(&method(:add_terminator))
65
+ end
66
+
67
+ def port_declarations
68
+ register_block
69
+ .declarations[:port]
70
+ .yield_self(&method(:sort_port_declarations))
71
+ .yield_self(&method(:add_terminator))
72
+ end
73
+
74
+ def signal_declarations
75
+ register_block.declarations[:signal]
76
+ end
77
+
78
+ def architecture_body_code
79
+ code_block(2) do |code|
80
+ register_block.generate_code(code, :register_block, :top_down)
81
+ register_block.generate_code(code, :register_file, :top_down, 1)
82
+ end
83
+ end
84
+
85
+ def sort_port_declarations(declarations)
86
+ declarations
87
+ .partition(&method(:clock_or_reset?))
88
+ .flatten
89
+ end
90
+
91
+ def clock_or_reset?(declaration)
92
+ [clock.to_s, reset.to_s]
93
+ .any? { |port_name| declaration.include?(port_name) }
94
+ end
95
+
96
+ def add_terminator(declarations)
97
+ declarations.map.with_index do |declaration, i|
98
+ (i == declarations.size - 1) && declaration ||
99
+ declaration + semicolon
100
+ end
101
+ end
102
+ end
103
+ end