2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
16 import Memory_AXI4 ::*;
17 import Semi_FIFOF :: *;
18 import AXI4_Types :: *;
19 import AXI4_Fabric :: *;
20 import Connectable :: *;
21 import ConfigReg :: *;
25 import defined_types::*;
26 `include "defined_parameters.bsv"
29 `define Num_DMA_Channels 7
30 `define Num_Peripherals 12
32 `define Num_Slaves TAdd#(`Num_Peripherals,2)
34 `define DMA_cfg_addr_start 64'h00000000
35 `define DMA_cfg_addr_end 64'h000000FF
36 `define Peripheral1_addr_start 64'h00001000
37 `define Peripheral1_addr_end 64'h00001FFF
38 `define Peripheral2_addr_start 64'h00002000
39 `define Peripheral2_addr_end 64'h00002FFF
40 `define Peripheral3_addr_start 64'h00003000
41 `define Peripheral3_addr_end 64'h00003FFF
42 `define MainMemory_addr_start 64'h80000000
43 `define MainMemory_addr_end 64'hFFFFFFFF
45 typedef enum{Send_req,Get_resp} Mem_state deriving(Bits,Eq);
47 /*function Tuple2#(t , Bit#(`Addr_space)) fn_slave_addr_range(Integer i) provisos(Literal#(t));
49 0: return tuple2(`DMA_cfg_addr_start, `DMA_cfg_addr_end);
50 1: return tuple2(`MainMemory_addr_start, `MainMemory_addr_end);
51 2: return tuple2(`Peripheral1_addr_start, `Peripheral1_addr_end);
52 default: return tuple2(0,0);
56 function Tuple2 #(Bool, Bit#(TLog#(`Num_Slaves))) fn_addr_to_slave_num (Bit #(`PADDR) addr);
57 if(addr>=`MainMemory_addr_start && addr<=`MainMemory_addr_end)
58 return tuple2(True,1); //Memory
59 else if(addr>=`Peripheral1_addr_start && addr<=`Peripheral1_addr_end)
60 return tuple2(True,2); //Peripherals
61 else if(addr>=`Peripheral2_addr_start && addr<=`Peripheral2_addr_end)
62 return tuple2(True,3); //Peripherals
63 else if(addr>=`Peripheral3_addr_start && addr<=`Peripheral3_addr_end)
64 return tuple2(True,4); //Peripherals
65 else if(addr>=`DMA_cfg_addr_start && addr<= `DMA_cfg_addr_end)
66 return tuple2(True,0); //DMA config registers
68 return tuple2(False,0);
72 //(*mutually_exclusive= "get_read_response,get_write_response"*)
73 module mkTb_DMA(Empty);
74 DmaC#(`Num_DMA_Channels, `Num_Peripherals) dma <-mkDMA();//check parameter as DmaC-data type of mkDMA input takes two inputs
75 AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) processor <- mkAXI4_Master_Xactor();
76 Memory_IFC#(`MainMemory_addr_start,`Addr_space) main_memory <- mkMemory("MainMemory_MSB","MainMemory_LSB","MainMemory");
78 Memory_IFC#(`Peripheral1_addr_start,`Addr_space) peripheral1 <- mkMemory("Peripheral1_MSB", "Peripheral1_LSB", "Peripheral[1]");
79 Memory_IFC#(`Peripheral2_addr_start,`Addr_space) peripheral2 <- mkMemory("Peripheral2_MSB", "Peripheral2_LSB", "Peripheral[2]");
80 Memory_IFC#(`Peripheral3_addr_start,`Addr_space) peripheral3 <- mkMemory("Peripheral3_MSB", "Peripheral3_LSB", "Peripheral[2]");
81 /*for(Integer i=0; i<`Num_Peripherals; i=i+1) begin
82 let lv_base_addr= fn_slave_addr_range(i).tpl_1;
83 peripheral[i] <- mkMemory("Peripheral" +integerToString(i)+ "_MSB", "Peripheral" +integerToString(i)+ "_LSB", "Peripheral[" +integerToString(i)+ "]");
87 AXI4_Fabric_IFC #(`Num_Masters, `Num_Slaves, `PADDR, `Reg_width,`USERSPACE)
88 fabric <- mkAXI4_Fabric(fn_addr_to_slave_num());
90 //Connect the masters to fabric
91 mkConnection (processor.axi_side, fabric.v_from_masters [0]); //MASTER0: Processor
92 mkConnection (dma.mmu, fabric.v_from_masters [1]); //MASTER1: DMA's MMU
94 mkConnection(fabric.v_to_slaves[0],dma.cfg); //SLAVE1: Main Memory
95 mkConnection(fabric.v_to_slaves[1],main_memory.axi_slave); //SLAVE1: Main Memory
97 mkConnection(fabric.v_to_slaves[2],peripheral1.axi_slave); //SLAVE2: Peripheral1
98 mkConnection(fabric.v_to_slaves[3],peripheral2.axi_slave); //SLAVE2: Peripheral1
99 mkConnection(fabric.v_to_slaves[4],peripheral3.axi_slave); //SLAVE2: Peripheral1
100 /*for(Integer i=0; i<`Num_Peripherals; i=i+1)
101 mkConnection(fabric.v_to_slaves[i+2],peripheral[i].axi_slave); //SLAVE2 onwards: Various Peripherals*/
103 //Registers for reading instructions from Dummy processor
104 Reg#(Bit#(6)) index<-mkConfigReg(0); // states 0..7
105 Reg#(Bool) rg_read_flag<-mkConfigReg(False);
106 Reg#(Bool) rg_write_flag<-mkConfigReg(False);
107 RegFile#(Bit#(6),Bit#(136)) input_instructions <-mkRegFileFullLoad("trial.hex");
108 Reg#(Bit#(32)) rg_count <-mkReg(0);
109 Reg#(Bool) rg_done <-mkReg(False);
112 rg_count<= rg_count + 1;
114 $display($time,"\tCount: %d",rg_count);
119 rule proc_start_read(!rg_read_flag && !rg_done && input_instructions.sub(truncate(index))[65:64]==2'b00); //read operation
120 let x = input_instructions.sub(truncate(index));
125 $display($time,"\tTBMaster Processor: Sending Read Request to addr %h",addr);
126 let read_request = AXI4_Rd_Addr {araddr: zeroExtend(addr), arprot: 0, aruser: 0, arsize: zeroExtend(size), arlen: 0 , arburst: 1, // arburst: 00-FIXED 01-INCR 10-WRAP
127 arlock: 0, arcache: 0, arqos: 0,
128 arregion: 0, arid: 0 };
129 processor.i_rd_addr.enq(read_request);
130 //x[15:0]=fn_decr_cndtr(x[15:0],2,x[50:48]);//CHECK correct this code USE FUNCTION
132 rg_done<= unpack(stop);
135 rule proc_start_write(!rg_write_flag && !rg_done && input_instructions.sub(truncate(index))[65:64]==2'b01); //write operation
136 let x = input_instructions.sub(truncate(index));
141 $display($time,"\tTBMaster Processor: Sending Write Request");
142 let aw = AXI4_Wr_Addr { awaddr: zeroExtend(addr), awprot:0, awuser:0, awlen: 0, awsize: zeroExtend(size), awburst: 1,
143 awlock: 0, awcache: 0, awqos: 0,
144 awregion: 0, awid: 0 };
147 if(addr[2:0]=='b000) begin
149 lv_wdata= zeroExtend(wdata);
151 else if(addr[2:0]=='b100) begin
153 lv_wdata= {wdata,32'd0};
156 $display($time,"ERROR: Write to a wrong address");
158 let w = AXI4_Wr_Data {wdata: lv_wdata, wstrb: lv_strb, wlast:True, wid: 0}; //TODO generate wstrb to be 2'b10 for all regs except cmar and cpar
159 processor.i_wr_addr.enq(aw);
160 processor.i_wr_data.enq(w);
161 rg_write_flag<= True;
162 rg_done<= unpack(stop);
166 rule get_read_response1(rg_read_flag);
167 let response <- pop_o (processor.o_rd_data);
168 $display($time,"\tTBMaster Processor: Received read response with data %h",response.rdata);
169 rg_read_flag<= False;
172 rule get_write_response1(rg_write_flag);
173 let response <- pop_o (processor.o_wr_resp);
174 $display($time,"\tTBMaster Processor: Received write response");
175 rg_write_flag<= False;
178 ///////////////////////// SEND INTERRUPT FROM PERIPHERAL //////////////////////////////
179 rule rl_send_interrupt;
180 dma.interrupt_from_peripherals('d-1);
184 rule rl_read_interrupt_status(rg_count>20 && rg_count<60);
186 $display($time,"\tTBMaster Processor: Sending Read Request to addr 0 to read interrupt status...");
187 let read_request = AXI4_Rd_Addr {araddr: 0, arprot: 0, aruser: 0, arsize: zeroExtend(size), arlen: 0 , arburst: 1, // arburst: 00-FIXED 01-INCR 10-WRAP
188 arlock: 0, arcache: 0, arqos: 0,
189 arregion: 0, arid: 0 };
190 processor.i_rd_addr.enq(read_request);
191 //x[15:0]=fn_decr_cndtr(x[15:0],2,x[50:48]);//CHECK correct this code USE FUNCTION