lib/HDLRuby/std/memory.rb in HDLRuby-2.4.19 vs lib/HDLRuby/std/memory.rb in HDLRuby-2.4.20

- old
+ new

@@ -1702,9 +1702,130 @@ end end end + +# Queue memory of +size+ elements of +typ+ typ, syncrhonized on +clk+ +# (positive and negative edges) and reset on +rst+. +# At each rising edge of +clk+ a read and a write is guaranteed to be +# completed provided they are triggered. +# +# NOTE: this channel does not have any branch. +HDLRuby::High::Std.channel(:mem_queue) do |typ,size,clk,rst| + # The inner buffer of the queue. + typ[-size].inner :buffer + # The read and write pointers. + [size.width].inner :rptr, :wptr + # The read and write command signals. + inner :rreq, :wreq + # The read and write ack signals. + inner :rack, :wack + # The read/write data registers. + typ.inner :rdata, :wdata + + # The flags telling of the channel is synchronized + inner :rsync, :wsync + + # The process handling the decoupled access to the buffer. + par(clk.posedge) do + hif(rst) { rptr <= 0; wptr <= 0 } + helse do + hif(~rsync) do + hif (~rreq) { rack <= 0 } + hif(rreq & (~rack) & (rptr != wptr)) do + rdata <= buffer[rptr] + rptr <= (rptr + 1) % depth + rack <= 1 + end + end + + hif(~wsync) do + hif (~wreq) { wack <= 0 } + hif(wreq & (~wack) & (((wptr+1) % size) != rptr)) do + buffer[wptr] <= wdata + wptr <= (wptr + 1) % size + wack <= 1 + end + end + end + end + + reader_output :rreq, :rptr, :rsync + reader_input :rdata, :rack, :wptr, :buffer + + # The read primitive. + reader do |blk,target| + if (cur_behavior.on_event?(clk.posedge,clk.negedge)) then + # Same clk event, synchrone case: perform a direct access. + # Now perform the access. + top_block.unshift do + rsync <= 1 + rreq <= 0 + end + seq do + hif(rptr != wptr) do + # target <= rdata + target <= buffer[rptr] + rptr <= (rptr + 1) % size + blk.call if blk + end + end + else + # Different clk event, perform a decoupled access. + top_block.unshift do + rsync <= 0 + rreq <= 0 + end + par do + hif (~rack) { rreq <= 1 } + helsif(rreq) do + rreq <= 0 + target <= rdata + blk.call if blk + end + end + end + end + + writer_output :wreq, :wdata, :wptr, :wsync, :buffer + writer_input :wack, :rptr + + # The write primitive. + writer do |blk,target| + if (cur_behavior.on_event?(clk.negedge,clk.posedge)) then + # Same clk event, synchrone case: perform a direct access. + top_block.unshift do + wsync <= 1 + wreq <= 0 + end + hif(((wptr+1) % size) != rptr) do + buffer[wptr] <= target + wptr <= (wptr + 1) % size + blk.call if blk + end + else + # Different clk event, asynchrone case: perform a decoupled access. + top_block.unshift do + wsync <= 0 + wreq <= 0 + end + seq do + hif (~wack) do + wreq <= 1 + wdata <= target + end + helsif(wreq) do + wreq <= 0 + blk.call if blk + end + end + end + end +end + + + # HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}| # # Ensure typ is a type. # typ = typ.to_type # # Ensure nbank is an integer. # nbanks = nbanks.to_i