HDLRuby 2.2.17 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9512393bdc65c3c2ae471d471b30d911cb693b8c1bc18a20186320286f27602
4
- data.tar.gz: 8a5bce50d367d52c181779ce834b2cfb3ecb14fe3c6ce96388eade344692e616
3
+ metadata.gz: b9bca5842e518422f5e7b7edb864a8eae5955df19238cd9582a776d4ef6c7a1e
4
+ data.tar.gz: 6c094ebf5d69c8dbf57ddd800eca16aca88b4bc324db11eecac3f15569b633e3
5
5
  SHA512:
6
- metadata.gz: 8cc2e806c2eb5d5ea9e4bc2c5cc449f2a0f6ca7270b73232efcc3fb9ae7bacdd074e2995f9233547fc47dae4ccfd98ab9b41d3903cee87374247cc4f68e353e4
7
- data.tar.gz: 698b4bd637fe294d0bf27fa163ef3c52528260cf443482d9e9a4922a56032db8400d8f95af67a3b62d67e949840c437869512514cb0db575c5b8c7b1b9b7fad9
6
+ metadata.gz: f01e2f703bcade0db355c42e78267205ca3662c8b30589c5676eab6acaf334fac2a86205b600122e50f11eef3e6a17182dacb59b9a7821c3fa9d7aed90ebd6b7
7
+ data.tar.gz: 5c3b80eddb70a3f25f2941bc26c8e95a8f3a30f5020cb17d6a4a199678aacaab4ce0c5c4ffcd347c23b53bd86fb15d58392818673e57ca3d108aec0c5b062ed0
data/README.md CHANGED
@@ -2815,27 +2815,17 @@ This library provides a unified interface to complex communication protocols thr
2815
2815
  ### Using a channel
2816
2816
 
2817
2817
  A channel is used similarly to a pipe: it has an input where data can be written and an output where data can be read. The ordering of the data and the synchronization depend on the internals of the channel, e.g., a channel can be FIFO or LIFO. The interaction with the channel is done using the following methods:
2818
-
2819
- * `input <name>`: generate ports in the system for reading from the channel amd associate them to `name`
2820
- * `output <name>`: generate ports in the system for writing to the channel and associate them to `name`
2821
- * `inout <name>`: generate ports in the system for reading and writing to the channel and associate them to `name`
2822
- * `inner <name>`: generates inner signals for accessing directly the channel
2823
-
2824
- __Note__: `input`, `output`, `inout` and `inner` for channels work similarly to the ones of data types for declaring signals. In particular, `input`, `output` and `inout` are to be used in systems that do not include the channel and `inner` is to be used in the system that include the channel.
2825
-
2826
- When the channel ports are declared, they can be accessed using the following methods depending on whether they are writing or reading ports:
2827
2818
 
2828
2819
  * `write(<args>) <block>`: write to the channel and execute `block` when `write` completes. `args` is a list of arguments required for performing the write that depend on the channel.
2829
2820
  * `read(<args>) <block>`: read the channel and execute `block` when the read completes. `args` is a list of arguments required for performing the write that depend on the channel.
2830
2821
 
2822
+
2831
2823
  For example, a system sending successive 8-bit values through a channel can be described as follows:
2832
2824
 
2833
2825
  ```ruby
2834
2826
  system :producer8 do |channel|
2835
2827
  # Inputs of the producer: clock and reset.
2836
2828
  input :clk, :rst
2837
- # Instantiate the channel ports
2838
- channel.output :chi
2839
2829
  # Inner 8-bit counter for generating values.
2840
2830
  [8].inner :counter
2841
2831
 
@@ -2843,7 +2833,7 @@ system :producer8 do |channel|
2843
2833
  par(clk.posedge) do
2844
2834
  hif(rst) { counter <= 0 }
2845
2835
  helse do
2846
- chi.write(counter) { counter <= counter + 1 }
2836
+ channel.write(counter) { counter <= counter + 1 }
2847
2837
  end
2848
2838
  end
2849
2839
  end
@@ -2851,6 +2841,22 @@ end
2851
2841
 
2852
2842
  __Note__: In the code above, the channel is passed as generic argument of the system.
2853
2843
 
2844
+ The access points to a channel can also be handled individually by declaring ports using the following methods:
2845
+
2846
+ * `input <name>`: declares a port for reading from the channel and associate them to `name` if any
2847
+ * `output <name>`: declares a port for writing to the channel and associate them to `name` if any
2848
+ * `inout <name>`: declares a port for reading and writing to the channel and associate them to `name` if any
2849
+
2850
+ Such port can then be accessed using the same `read` and `write` method of a channel, the difference being that they can also be configured for new access procedure using the `wrap` method:
2851
+
2852
+ * `wrap(<args>) <code>`: creates a new port whose read or write procedure has the elements of `<args>` and the ones produced by `<code>` assign to the arguments of the read or write procedure.
2853
+
2854
+ For example, assuming `mem` is a channel whose read and write access have as argument the target address and data signals, the following code creates a port for always accessing at address 0:
2855
+
2856
+ ```ruby
2857
+ addr0 = channel.input.wrap(0)
2858
+ ```
2859
+
2854
2860
  ### Channel branches
2855
2861
 
2856
2862
  Some channel may include several branches, they are accessed by name using the following method:
@@ -2894,7 +2900,7 @@ Where `name` is the name of the channel and `block` is a procedure block describ
2894
2900
  The first argument of the block must be the following:
2895
2901
  - `blk`: the block to execute when the write completes.
2896
2902
  Other arguments can be freely defined, and will be required by the `write` command.
2897
- * `brancher(name) <block>`: defines branch named +name+ described in `block`. The content of block can be any content valid for a channel, with the additional possiblity to access the internals of the upper channel.
2903
+ * `brancher(name) <block>`: defines branch named +name+ described in `block`. The content of block can be any content valid for a channel, with the additional possibility to access the internals of the upper channel.
2898
2904
 
2899
2905
  For example, a channel implemented by a simple register of generic type `typ`, that can be set to 0 using the `reset` command can be described as follows:
2900
2906
 
@@ -0,0 +1,96 @@
1
+ require 'std/memory.rb'
2
+ require 'std/linear.rb'
3
+ # require 'std/timing.rb'
4
+
5
+ include HDLRuby::High::Std
6
+
7
+
8
+ system :fir do |typ,iChannel,oChannel,coefs|
9
+ input :clk, :rst, :req
10
+ output :ack
11
+ # Declare the input port.
12
+ iChannel.input :iPort
13
+ # Declare the output port.
14
+ oChannel.output :oPort
15
+
16
+ # Declares the data registers.
17
+ datas = coefs.map.with_index do |coef,id|
18
+ coef.type.inner :"data_#{id}"
19
+ end
20
+
21
+ inner :req2
22
+
23
+
24
+ # Generate the mac pipeline.
25
+ mac_np(typ,clk.posedge,req2,ack,
26
+ datas.map{|data| channel_port(data) },
27
+ coefs.map{|coef| channel_port(coef) }, oPort)
28
+
29
+ # Generate the data transfer through the pipeline.
30
+ par(clk.posedge) do
31
+ req2 <= 0
32
+ hif(rst) { datas.each { |d| d <= 0 } }
33
+ hif(req) do
34
+ iPort.read(datas[0]) do
35
+ # datas.each_cons(2) { |d0,d1| d1 <= d0 }
36
+ datas[1..-1] <= datas[0..-2]
37
+ end
38
+ req2 <= 1
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+
45
+
46
+
47
+ system :work do
48
+
49
+ inner :clk,:rst,:req,:ack
50
+
51
+ # The input memory.
52
+ mem_rom([8],8,clk,rst,
53
+ [_00000001,_00000010,_00000011,_00000100,
54
+ _00000101,_00000110,_00000111,_00001000]).(:iMem)
55
+ # The output memory.
56
+ mem_dual([8],8,clk,rst).(:oMem)
57
+ # The coefficients.
58
+ coefs = [_11001100,_00110011,_10101010,_01010101,
59
+ _11110000,_00001111,_11100011,_00011100]
60
+
61
+ # The filter
62
+ fir([8],iMem.branch(:rinc),oMem.branch(:winc),coefs).(:my_fir).(clk,rst,req,ack)
63
+
64
+ # iMem.branch(:rinc).inner :port
65
+ # [8].inner :a
66
+ # par(clk.posedge) do
67
+ # hif(req) { port.read(a) }
68
+ # end
69
+
70
+ timed do
71
+ req <= 0
72
+ clk <= 0
73
+ rst <= 0
74
+ !10.ns
75
+ clk <= 1
76
+ !10.ns
77
+ clk <= 0
78
+ rst <= 1
79
+ !10.ns
80
+ clk <= 1
81
+ !10.ns
82
+ clk <= 0
83
+ rst <= 0
84
+ !10.ns
85
+ clk <= 1
86
+ !10.ns
87
+ req <= 1
88
+ clk <= 0
89
+ 64.times do
90
+ !10.ns
91
+ clk <= 1
92
+ !10.ns
93
+ clk <= 0
94
+ end
95
+ end
96
+ end
@@ -63,12 +63,13 @@ end
63
63
 
64
64
 
65
65
  # A system writing indefinitely to a channel.
66
+ # Checking usage of channel without declaring a port.
66
67
  system :producer8 do |channel|
67
- # puts "channel=#{channel}"
68
+ # puts "channel=#{channel}, channel methods=#{channel.methods}"
68
69
  # Inputs of the producer: clock and reset.
69
70
  input :clk, :rst
70
- # Instantiate the channel ports
71
- channel.output :ch
71
+ # # Instantiate the channel ports
72
+ # channel.output :ch
72
73
  # Inner 8-bit counter for generating values.
73
74
  [8].inner :counter
74
75
 
@@ -76,7 +77,8 @@ system :producer8 do |channel|
76
77
  par(clk.posedge) do
77
78
  hif(rst) { counter <= 0 }
78
79
  helse do
79
- ch.write(counter) { counter <= counter + 1 }
80
+ # ch.write(counter) { counter <= counter + 1 }
81
+ channel.write(counter) { counter <= counter + 1 }
80
82
  end
81
83
  end
82
84
  end
@@ -96,20 +98,59 @@ system :consummer8 do |channel|
96
98
  end
97
99
  end
98
100
 
101
+ # A system reading indefinitely from a channel.
102
+ # Version without port declaration.
103
+ system :consummer16 do |channel|
104
+ # Input of the consummer: a clock is enough.
105
+ input :clk
106
+ # # Instantiate the channel ports
107
+ # channel.input :ch
108
+ # Inner buffer for storing the cunsummed value.
109
+ [16].inner :buf
110
+
111
+ # The value consumption process
112
+ par(clk.posedge) do
113
+ # ch.read(buf)
114
+ channel.read(buf)
115
+ end
116
+ end
117
+
99
118
 
100
119
  # A system testing the handshaker.
101
120
  system :hs_test do
102
121
  input :clk,:rst
103
122
 
104
- # Declares the handshaker
105
- handshaker([8]).(:hs)
123
+ # Declares two handshakers
124
+ handshaker([8]).(:hs0)
125
+ handshaker([16]).(:hs1)
106
126
 
107
127
  # # Sets the reset.
108
128
  # par(rst.posedge) { hs.reset }
129
+
130
+ # For the first handshake
109
131
 
110
132
  # Instantiate the producer.
111
- producer8(hs).(:producerI).(clk,rst)
133
+ producer8(hs0).(:producerI).(clk,rst)
112
134
 
113
135
  # Instantiate the consummer.
114
- consummer8(hs).(:consummerI).(clk)
136
+ consummer8(hs0).(:consummerI).(clk)
137
+
138
+ # For the second handshaker
139
+
140
+ # Instantiatethe consummer.
141
+ consummer16(hs1).(:consummer2I).(clk)
142
+
143
+ # Produce from within.
144
+ [16].inner :counter
145
+
146
+ # hs1.output :port
147
+
148
+ par(clk.posedge) do
149
+ hif(rst) { counter <= 0 }
150
+ helse do
151
+ # port.write(counter) { counter <= counter + 1 }
152
+ hs1.write(counter) { counter <= counter + 1 }
153
+ end
154
+ end
155
+
115
156
  end
@@ -15,27 +15,36 @@ system :testmat do
15
15
  inner :clk,:rst, :req
16
16
 
17
17
  # Input memories
18
- mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL0)
18
+ # mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL0)
19
+ # The first memory is 4-bank for testing purpose.
20
+ mem_bank([8],4,256/4,clk,rst, rinc: :rst,winc: :rst).(:memL0)
21
+ # The others are standard dual-edge memories.
19
22
  mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memL1)
20
23
  mem_dual([8],256,clk,rst, rinc: :rst,winc: :rst).(:memR)
21
24
  # Access ports.
22
- memL0.branch(:rinc).inner :readL0
23
- memL1.branch(:rinc).inner :readL1
24
- memR.branch(:rinc).inner :readR
25
+ # # memL0.branch(:rinc).inner :readL0
26
+ # # memL1.branch(:rinc).inner :readL1
27
+ # # memR.branch(:rinc).inner :readR
28
+ # memL0.branch(:rinc).input :readL0
29
+ # memL1.branch(:rinc).input :readL1
30
+ # memR.branch(:rinc).input :readR
25
31
 
26
32
  # Prepares the left and acc arrays.
27
- lefts = [readL0, readL1]
33
+ # lefts = [readL0, readL1]
34
+ lefts = [memL0.branch(:rinc), memL1.branch(:rinc)]
28
35
 
29
36
  # Accumulators memory.
30
37
  mem_file([8],2,clk,rst,rinc: :rst).(:memAcc)
31
- memAcc.branch(:anum).inner :accs
38
+ # # memAcc.branch(:anum).inner :accs
39
+ memAcc.branch(:anum).inout :accs
32
40
  accs_out = [accs.wrap(0), accs.wrap(1)]
33
41
 
34
42
  # Layer 0 ack.
35
43
  inner :ack0
36
44
 
37
45
  # Instantiate the matrix product.
38
- mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
46
+ # mac_n1([8],clk,req,ack0,lefts,readR,accs_out)
47
+ mac_n1([8],clk,req,ack0,lefts,memR.branch(:rinc),accs_out)
39
48
 
40
49
  # Translation.
41
50
  # Translation memory.
@@ -43,10 +52,12 @@ system :testmat do
43
52
  # Tarnslation result
44
53
  mem_file([8],2,clk,rst,rinc: :rst).(:memF)
45
54
  # Access ports.
46
- memT.branch(:anum).inner :readT
47
- memF.branch(:anum).inner :writeF
55
+ # # memT.branch(:anum).inner :readT
56
+ # # memF.branch(:anum).inner :writeF
57
+ memT.branch(:anum).input :readT
58
+ memF.branch(:anum).output :writeF
48
59
  regRs = [ readT.wrap(0), readT.wrap(1) ]
49
- regLs = [ accs.wrap(0), accs.wrap(1) ]
60
+ regLs = accs_out
50
61
  regs = [ writeF.wrap(0), writeF.wrap(1) ]
51
62
 
52
63
  # Translater ack.
@@ -61,9 +72,10 @@ system :testmat do
61
72
  # Input memories.
62
73
  mem_dual([8],2,clk,rst, rinc: :rst,winc: :rst).(:mem2L0)
63
74
  # Access ports.
64
- mem2L0.branch(:rinc).inner :read2L0
65
- # memAcc.branch(:rinc).inner :accsR
66
- memF.branch(:rinc).inner :readF
75
+ # # mem2L0.branch(:rinc).inner :read2L0
76
+ # # memF.branch(:rinc).inner :readF
77
+ # mem2L0.branch(:rinc).input :read2L0
78
+ # memF.branch(:rinc).input :readF
67
79
 
68
80
  # Second layer ack.
69
81
  inner :ack1
@@ -73,29 +85,40 @@ system :testmat do
73
85
 
74
86
  sub do
75
87
  # Instantiate the second matrix product.
76
- # mac([8],clk,req,read2L0,accsR,res)
77
- mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
88
+ # mac([8],clk,ackT,ack1,read2L0,readF,channel_port(res))
89
+ mac([8],clk,ackT,ack1,mem2L0.branch(:rinc),memF.branch(:rinc),
90
+ channel_port(res))
78
91
  end
79
92
 
80
93
 
81
94
 
82
95
  # The memory initializer.
83
- memL0.branch(:winc).inner :writeL0
84
- memL1.branch(:winc).inner :writeL1
85
- memR.branch(:winc).inner :writeR
86
- memT.branch(:winc).inner :writeT
87
- mem2L0.branch(:winc).inner :write2L0
96
+ # # memL0.branch(:winc).inner :writeL0
97
+ # # memL1.branch(:winc).inner :writeL1
98
+ # # memR.branch(:winc).inner :writeR
99
+ # # memT.branch(:winc).inner :writeT
100
+ # # mem2L0.branch(:winc).inner :write2L0
101
+ # memL0.branch(:winc).output :writeL0
102
+ # memL1.branch(:winc).output :writeL1
103
+ # memR.branch(:winc).output :writeR
104
+ # mem2L0.branch(:winc).output :write2L0
105
+ # memT.branch(:winc).output :writeT
88
106
  inner :fill, :fill2
89
107
  [8].inner :val
90
108
  par(clk.posedge) do
91
109
  hif(fill) do
92
- writeL0.write(val)
93
- writeL1.write(val+1)
94
- writeR.write(val+1)
110
+ # writeL0.write(val)
111
+ # writeL1.write(val+1)
112
+ # writeR.write(val+1)
113
+ memL0.branch(:winc).write(val)
114
+ memL1.branch(:winc).write(val+1)
115
+ memR.branch(:winc).write(val+1)
95
116
  end
96
117
  hif(fill2) do
97
- write2L0.write(val+2)
98
- writeT.write(val+2)
118
+ # write2L0.write(val+2)
119
+ # writeT.write(val+2)
120
+ mem2L0.branch(:winc).write(val+2)
121
+ memT.branch(:winc).write(val+2)
99
122
  end
100
123
  end
101
124
 
@@ -0,0 +1,69 @@
1
+ require 'std/loop.rb'
2
+
3
+ include HDLRuby::High::Std
4
+
5
+ system :with_loop do
6
+
7
+ # The clock and reset
8
+ inner :clk, :rst
9
+ # The running signals.
10
+ inner :doit0, :doit1
11
+ # The signal to check for finishing.
12
+ inner :over
13
+
14
+ # A counter.
15
+ [8].inner :count, :count2
16
+
17
+ # The first loop: basic while.
18
+ lp0 = while_loop(clk, proc{count<=0}, count<15) { count <= count + 1 }
19
+
20
+ # The second loop: 10 times.
21
+ lp1 = times_loop(clk,10) { count2 <= count2+2 }
22
+ # Control it using doit1 as req and over as ack.
23
+ rst_req_ack(clk.posedge,rst,doit1,over,lp1)
24
+
25
+ par(clk.posedge) do
26
+ doit1 <= 0
27
+ hif(rst) do
28
+ lp0.reset()
29
+ # lp1.reset()
30
+ # doit1 <= 0
31
+ count2 <= 0
32
+ over <= 0
33
+ end
34
+ helse do
35
+ hif(doit0) { lp0.run }
36
+ lp0.finish { doit0 <= 0; doit1 <= 1 }# ; lp1.run }
37
+ hif(doit1) { lp1.run; lp0.reset() }
38
+ # lp1.finish { over <= 1; doit1 <= 0 }
39
+ # Second pass for first loop.
40
+ hif(over) { lp0.run }
41
+ end
42
+ end
43
+
44
+ timed do
45
+ clk <= 0
46
+ rst <= 0
47
+ doit0 <= 0
48
+ !10.ns
49
+ clk <= 1
50
+ !10.ns
51
+ clk <= 0
52
+ rst <= 1
53
+ !10.ns
54
+ clk <= 1
55
+ !10.ns
56
+ clk <= 0
57
+ rst <= 0
58
+ doit0 <= 1
59
+ !10.ns
60
+ clk <= 1
61
+ !10.ns
62
+ 64.times do
63
+ clk <= 0
64
+ !10.ns
65
+ clk <= 1
66
+ !10.ns
67
+ end
68
+ end
69
+ end