replace defined_parameters with instance_defines
[shakti-peripherals.git] / src / peripherals / bootrom / BootRom.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
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.
10
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package BootRom;
15 import defined_types::*;
16 `include "instance_defines.bsv"
17 import BRAMCore :: *;
18 import DReg::*;
19 import Semi_FIFOF :: *;
20 import AXI4_Types :: *;
21 import AXI4_Fabric :: *;
22 import BUtils::*;
23 import axi_addr_generator::*;
24
25 interface BootRom_IFC;
26 interface AXI4_Slave_IFC#(`PADDR,`Reg_width,`USERSPACE) axi_slave;
27 endinterface
28 typedef enum{Idle,HandleBurst} Mem_state deriving(Bits,Eq);
29 (*synthesize*)
30 module mkBootRom (BootRom_IFC);
31
32 // we create 2 32-bit BRAMs since the xilinx tool is easily able to map them to BRAM32BE cells
33 // which makes it easy to use data2mem for updating the bit file.
34 BRAM_PORT#(Bit#(13),Bit#(32)) dmemMSB <- mkBRAMCore1Load(valueOf(TExp#(13)),False,"boot.MSB",False);
35 BRAM_PORT#(Bit#(13),Bit#(32)) dmemLSB <- mkBRAMCore1Load(valueOf(TExp#(13)),False,"boot.LSB",False);
36
37 AXI4_Slave_Xactor_IFC #(`PADDR, `Reg_width, `USERSPACE) s_xactor <- mkAXI4_Slave_Xactor;
38
39 Reg#(Mem_state) rd_state <-mkReg(Idle);
40 Reg#(Mem_state) wr_state <-mkReg(Idle);
41 Reg#(Bit#(8)) rg_readburst_counter<-mkReg(0);
42 Reg#(AXI4_Rd_Addr #(`PADDR,`USERSPACE)) rg_read_packet <-mkReg(?);
43 Reg#(AXI4_Wr_Resp #(`USERSPACE)) rg_write_response <-mkReg(?);
44
45 rule rl_wr_respond(wr_state==Idle);
46 let aw <- pop_o (s_xactor.o_wr_addr);
47 let w <- pop_o (s_xactor.o_wr_data);
48 let b = AXI4_Wr_Resp {bresp: AXI4_SLVERR, buser: aw.awuser, bid:aw.awid};
49 rg_write_response<=b;
50 $display($time,"\tBootROM: Illegal Write operation on BootROM");
51 if(aw.awburst!=0)
52 wr_state<=HandleBurst;
53 else
54 s_xactor.i_wr_resp.enq (b);
55 endrule
56
57 rule rl_wr_burst_response(wr_state==HandleBurst);
58 let w <- pop_o (s_xactor.o_wr_data);
59 if(w.wlast) begin
60 wr_state<=Idle;
61 s_xactor.i_wr_resp.enq (rg_write_response);
62 end
63 endrule
64
65 rule rl_rd_request(rd_state==Idle);
66 let ar<- pop_o(s_xactor.o_rd_addr);
67 rg_read_packet<=ar;
68 Bit#(13) index_address=(ar.araddr-`BootRomBase)[15:3];
69 dmemLSB.put(False,index_address,?);
70 dmemMSB.put(False,index_address,?);
71 rd_state<=HandleBurst;
72 `ifdef verbose $display($time,"\tBootROM: Recieved Read Request for Address: %h Index Address: %h",ar.araddr,index_address); `endif
73 endrule
74
75 rule rl_rd_response(rd_state==HandleBurst);
76 Bit#(`Reg_width) data0 = {dmemMSB.read(),dmemLSB.read()};
77 AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data {rresp: AXI4_OKAY, rdata: data0 ,rlast:rg_readburst_counter==rg_read_packet.arlen, ruser: 0, rid:rg_read_packet.arid};
78 let transfer_size=rg_read_packet.arsize;
79 let address=rg_read_packet.araddr;
80 if(transfer_size==2)begin // 32 bit
81 if(address[2:0]==0)
82 r.rdata=duplicate(data0[31:0]);
83 else
84 r.rdata=duplicate(data0[63:32]);
85 end
86 else if (transfer_size=='d1)begin // half_word
87 if(address[2:0] ==0)
88 r.rdata = duplicate(data0[15:0]);
89 else if(address[2:0] ==2)
90 r.rdata = duplicate(data0[31:16]);
91 else if(address[2:0] ==4)
92 r.rdata = duplicate(data0[47:32]);
93 else if(address[2:0] ==6)
94 r.rdata = duplicate(data0[63:48]);
95 end
96 else if (transfer_size=='d0) begin// one byte
97 if(address[2:0] ==0)
98 r.rdata = duplicate(data0[7:0]);
99 else if(address[2:0] ==1)
100 r.rdata = duplicate(data0[15:8]);
101 else if(address[2:0] ==2)
102 r.rdata = duplicate(data0[23:16]);
103 else if(address[2:0] ==3)
104 r.rdata = duplicate(data0[31:24]);
105 else if(address[2:0] ==4)
106 r.rdata = duplicate(data0[39:32]);
107 else if(address[2:0] ==5)
108 r.rdata = duplicate(data0[47:40]);
109 else if(address[2:0] ==6)
110 r.rdata = duplicate(data0[55:48]);
111 else if(address[2:0] ==7)
112 r.rdata = duplicate(data0[63:56]);
113 end
114 s_xactor.i_rd_data.enq(r);
115 address=burst_address_generator(rg_read_packet.arlen, rg_read_packet.arsize, rg_read_packet.arburst,rg_read_packet.araddr);
116 Bit#(13) index_address=(address-`BootRomBase)[15:3];
117 if(rg_readburst_counter==rg_read_packet.arlen)begin
118 rg_readburst_counter<=0;
119 rd_state<=Idle;
120 end
121 else begin
122 dmemLSB.put(False,index_address,?);
123 dmemMSB.put(False,index_address,?);
124 rg_readburst_counter<=rg_readburst_counter+1;
125 end
126 rg_read_packet.araddr<=address;
127 Bit#(64) new_data=r.rdata;
128 `ifdef verbose $display($time,"\tBootROM : Responding Read Request with CurrAddr: %h Data: %8h BurstCounter: %d BurstValue: %d NextAddress: %h",rg_read_packet.araddr,new_data,rg_readburst_counter,rg_read_packet.arlen,address); `endif
129 endrule
130
131 interface axi_slave= s_xactor.axi_side;
132 endmodule
133 endpackage