abstractaccelerator/opene906/smart_run/logical/mem/iahb_mem_ctrl.v

422 lines
12 KiB
Coq
Raw Permalink Normal View History

2022-02-21 18:41:54 +08:00
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module iahb_mem_ctrl(
lite_mmc_hsel,
lite_yy_haddr,
lite_yy_hsize,
lite_yy_htrans,
lite_yy_hwdata,
lite_yy_hwrite,
mmc_lite_hrdata,
mmc_lite_hready,
mmc_lite_hresp,
pad_biu_bigend_b,
pad_cpu_rst_b,
pll_core_cpuclk
);
// &Ports; @22
input lite_mmc_hsel;
input [31:0] lite_yy_haddr;
input [2 :0] lite_yy_hsize;
input [1 :0] lite_yy_htrans;
input [31:0] lite_yy_hwdata;
input lite_yy_hwrite;
input pad_biu_bigend_b;
input pad_cpu_rst_b;
input pll_core_cpuclk;
output [31:0] mmc_lite_hrdata;
output mmc_lite_hready;
output [1 :0] mmc_lite_hresp;
// &Regs; @23
reg [15:0] addr_holding;
reg [3 :0] lite_mem_wen;
reg lite_read_bypass;
reg lite_read_bypass_vld;
reg lite_read_stall;
reg lite_read_stall_vld;
reg [31:0] lite_wbuf_addr;
reg [31:0] lite_wbuf_data;
reg [2 :0] lite_wbuf_size;
reg lite_write_req;
reg lite_write_stall;
// &Wires; @24
wire lite_addr_hit;
wire lite_addr_no_hit;
wire [31:0] lite_bypass_data;
wire [31:0] lite_mem_addr;
wire lite_mem_cen;
wire [31:0] lite_mem_din;
wire [31:0] lite_mem_dout;
wire lite_mmc_hsel;
wire lite_read_addr_hit_with_bypass;
wire lite_read_addr_hit_with_stall;
wire lite_read_req;
wire lite_wbuf_update;
wire lite_write_cplt;
wire lite_write_en;
wire lite_write_req_en;
wire lite_write_stall_en;
wire [31:0] lite_yy_haddr;
wire [2 :0] lite_yy_hsize;
wire [31:0] lite_yy_hwdata;
wire lite_yy_hwrite;
wire [31:0] mmc_lite_hrdata;
wire mmc_lite_hready;
wire [1 :0] mmc_lite_hresp;
wire pad_biu_bigend_b;
wire pad_cpu_rst_b;
wire pll_core_cpuclk;
wire [7 :0] ram0_din;
wire [7 :0] ram0_dout;
wire [7 :0] ram1_din;
wire [7 :0] ram1_dout;
wire [7 :0] ram2_din;
wire [7 :0] ram2_dout;
wire [7 :0] ram3_din;
wire [7 :0] ram3_dout;
wire [15:0] ram_addr;
wire ram_clk;
wire [3 :0] ram_wen;
parameter IMEM_WIDTH = 18;
// &Force("nonport","lite_mem_addr"); @27
// &Force("nonport","lite_mem_cen"); @28
// &Force("nonport","lite_mem_din"); @29
// &Force("nonport","lite_mem_dout"); @30
// &Force("nonport","lite_mem_wen"); @31
// &Force("input","lite_yy_htrans"); @32
// &Force("bus", "lite_yy_htrans", 1, 0); @33
// //&Force("nonport",""); @34
// //&Force("nonport",""); @35
// //&Force("nonport",""); @36
// //&Force("nonport",""); @37
// //&Force("nonport",""); @38
// //&Force("nonport",""); @39
// //&Force("nonport",""); @40
//write buffer
assign lite_wbuf_update = lite_yy_hwrite && lite_mmc_hsel;
always @ (posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
lite_wbuf_addr[31:0] <= 32'b0;
lite_wbuf_size[2:0] <= 3'b0;
end
else if (lite_wbuf_update)
begin
lite_wbuf_addr[31:0] <= lite_yy_haddr;
lite_wbuf_size[2:0] <= lite_yy_hsize;
end
//else if (lite_write_cplt)
//begin
// lite_wbuf_addr[31:0] <= 32'b0;
// lite_wbuf_size[2:0] <= 3'b0;
//end
end
//write data
always @ (posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
lite_wbuf_data[31:0] <= 32'b0;
end
else if (lite_write_req)
begin
lite_wbuf_data[31:0] <= lite_yy_hwdata[31:0];
end
end
//read first and wirte will stall when address don't hit
assign lite_write_stall_en = lite_write_req && lite_addr_no_hit && lite_read_req;
always @ (posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
lite_write_stall <= 1'b0;
end
else if (lite_write_stall_en)
begin
lite_write_stall <= 1'b1;
end
else if (lite_write_cplt)
begin
lite_write_stall <=1'b0;
end
end
//write request from bus interface
assign lite_write_req_en = lite_yy_hwrite && lite_mmc_hsel;
always @ (posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
lite_write_req <= 1'b0;
end
else if (lite_write_req_en)
begin
lite_write_req <= 1'b1;
end
else
begin
lite_write_req <= 1'b0;
end
end
//read bypass and read stall
always @(posedge pll_core_cpuclk or negedge pad_cpu_rst_b)
begin
if(!pad_cpu_rst_b)
begin
lite_read_bypass <= 1'b0;
lite_read_stall <= 1'b0;
end
else
begin
lite_read_bypass <= lite_read_addr_hit_with_bypass;
lite_read_stall <= lite_read_addr_hit_with_stall;
end
end
//no read first and write request or write stall
assign lite_write_en = ((lite_write_req | lite_write_stall) && (lite_addr_hit | (lite_yy_hwrite && lite_mmc_hsel) | ~lite_mmc_hsel));
assign lite_bypass_data[31:0] = lite_wbuf_data[31:0];
//write complete
assign lite_write_cplt = (lite_write_req | lite_write_stall) && (lite_addr_hit | ~lite_mmc_hsel | (lite_yy_hwrite && lite_mmc_hsel));
//read request
assign lite_read_req = ~lite_yy_hwrite && lite_mmc_hsel;
//address hit
assign lite_addr_no_hit = (lite_yy_haddr[31:2] != lite_wbuf_addr[31:2]);
assign lite_addr_hit = ~lite_addr_no_hit;
//address hit and read will bypass
assign lite_read_addr_hit_with_bypass = lite_read_req && (lite_write_req | lite_write_stall) && lite_addr_hit && lite_read_bypass_vld;
//address hit but read will stall
assign lite_read_addr_hit_with_stall = lite_read_req && (lite_write_req | lite_write_stall) && lite_addr_hit && lite_read_stall_vld;
//read bypass or stall
// &CombBeg; @140
always @( lite_yy_haddr[1:0]
or lite_wbuf_addr[1:0]
or lite_wbuf_size[2:0]
or lite_yy_hsize[2:0])
begin
casez({lite_wbuf_size[2:0],lite_yy_hsize[2:0],lite_wbuf_addr[1:0],lite_yy_haddr[1:0]})
//st.b/ld.b
10'b000_000_00_00,
10'b000_000_01_01,
10'b000_000_10_10,
10'b000_000_11_11:
begin
lite_read_bypass_vld = 1'b1;
lite_read_stall_vld = 1'b0;
end
//st.b/ld.h
10'b000_001_??_??:
begin
lite_read_stall_vld = 1'b1;
lite_read_bypass_vld = 1'b0;
end
//st.b/ld.w
10'b000_010_??_??:
begin
lite_read_stall_vld = 1'b1;
lite_read_bypass_vld = 1'b0;
end
//st.h/ld.b
10'b001_000_0?_0?,
10'b001_000_1?_1?:
begin
lite_read_bypass_vld = 1'b1;
lite_read_stall_vld = 1'b0;
end
//st.h/ld.h
10'b001_001_0?_0?,
10'b001_001_1?_1?:
begin
lite_read_bypass_vld = 1'b1;
lite_read_stall_vld = 1'b0;
end
//st.h/ld.w
10'b001_010_??_??:
begin
lite_read_stall_vld = 1'b1;
lite_read_bypass_vld = 1'b0;
end
//st.w/all lds
10'b010_???_??_??:
begin
lite_read_bypass_vld = 1'b1;
lite_read_stall_vld = 1'b0;
end
default:
begin
lite_read_bypass_vld = 1'b0;
lite_read_stall_vld = 1'b0;
end
endcase
// &CombEnd; @195
end
//memory select
assign lite_mem_cen = ~(lite_read_req | lite_write_req | lite_write_stall);
//memory write enable
// &CombBeg; @202
always @( lite_wbuf_addr[1:0]
or lite_wbuf_size[2:0]
or pad_biu_bigend_b
or lite_write_en)
begin
case({pad_biu_bigend_b, lite_write_en, lite_wbuf_size[2:0], lite_wbuf_addr[1:0]})
7'b0100000:
begin
lite_mem_wen[3:0] = 4'b0111;
end
7'b0100001:
begin
lite_mem_wen[3:0] = 4'b1011;
end
7'b0100010:
begin
lite_mem_wen[3:0] = 4'b1101;
end
7'b0100011:
begin
lite_mem_wen[3:0] = 4'b1110;
end
7'b0100100:
begin
lite_mem_wen[3:0] = 4'b0011;
end
7'b0100110:
begin
lite_mem_wen[3:0] = 4'b1100;
end
7'b0101000:
begin
lite_mem_wen[3:0] = 4'b0000;
end
7'b1100000:
begin
lite_mem_wen[3:0] = 4'b1110;
end
7'b1100001:
begin
lite_mem_wen[3:0] = 4'b1101;
end
7'b1100010:
begin
lite_mem_wen[3:0] = 4'b1011;
end
7'b1100011:
begin
lite_mem_wen[3:0] = 4'b0111;
end
7'b1100100:
begin
lite_mem_wen[3:0] = 4'b1100;
end
7'b1100110:
begin
lite_mem_wen[3:0] = 4'b0011;
end
7'b1101000:
begin
lite_mem_wen[3:0] = 4'b0000;
end
default:
begin
lite_mem_wen[3:0] = 4'b1111;
end
endcase
// &CombEnd; @265
end
assign lite_mem_addr[31:0] = (lite_write_en | lite_read_stall) ? lite_wbuf_addr[31:0] : lite_yy_haddr[31:0];
assign lite_mem_din[31:0] = (lite_write_stall) ? lite_wbuf_data[31:0] : lite_yy_hwdata[31:0];
assign mmc_lite_hrdata[31:0] = lite_read_bypass ? lite_bypass_data[31:0] : lite_mem_dout[31:0];
assign mmc_lite_hready = !lite_read_stall;
assign mmc_lite_hresp[1:0] = 2'b0;
//memory
always @(posedge pll_core_cpuclk)
begin
if(!lite_mem_cen)
addr_holding[IMEM_WIDTH-3:0] <= lite_mem_addr[IMEM_WIDTH-1:2];
end
assign ram_clk = pll_core_cpuclk;
assign ram_addr[IMEM_WIDTH-3:0] = lite_mem_cen ? addr_holding[IMEM_WIDTH-3:0] : lite_mem_addr[IMEM_WIDTH-1:2];
assign ram_wen[0] = !lite_mem_cen && !lite_mem_wen[0];
assign ram_wen[1] = !lite_mem_cen && !lite_mem_wen[1];
assign ram_wen[2] = !lite_mem_cen && !lite_mem_wen[2];
assign ram_wen[3] = !lite_mem_cen && !lite_mem_wen[3];
assign ram0_din[7:0] = lite_mem_din[7:0];
assign ram1_din[7:0] = lite_mem_din[15:8];
assign ram2_din[7:0] = lite_mem_din[23:16];
assign ram3_din[7:0] = lite_mem_din[31:24];
assign lite_mem_dout[31:0] = {ram3_dout[7:0], ram2_dout[7:0], ram1_dout[7:0], ram0_dout[7:0]};
soc_fpga_ram #(8, IMEM_WIDTH-2) ram0(
.PortAClk (ram_clk),
.PortAAddr(ram_addr),
.PortADataIn (ram0_din),
.PortAWriteEnable(ram_wen[0]),
.PortADataOut(ram0_dout));
soc_fpga_ram #(8, IMEM_WIDTH-2) ram1(
.PortAClk (ram_clk),
.PortAAddr(ram_addr),
.PortADataIn (ram1_din),
.PortAWriteEnable(ram_wen[1]),
.PortADataOut(ram1_dout));
soc_fpga_ram #(8, IMEM_WIDTH-2) ram2(
.PortAClk (ram_clk),
.PortAAddr(ram_addr),
.PortADataIn (ram2_din),
.PortAWriteEnable(ram_wen[2]),
.PortADataOut(ram2_dout));
soc_fpga_ram #(8, IMEM_WIDTH-2) ram3(
.PortAClk (ram_clk),
.PortAAddr(ram_addr),
.PortADataIn (ram3_din),
.PortAWriteEnable(ram_wen[3]),
.PortADataOut(ram3_dout));
// &Force("nonport", "ram_addr"); @324
// &Force("nonport", "ram0_din"); @325
// &Force("nonport", "ram1_din"); @326
// &Force("nonport", "ram2_din"); @327
// &Force("nonport", "ram3_din"); @328
// &Force("nonport", "ram0_dout"); @329
// &Force("nonport", "ram1_dout"); @330
// &Force("nonport", "ram2_dout"); @331
// &Force("nonport", "ram3_dout"); @332
// &Force("nonport", "ram_wen"); @333
// &Force("nonport", "ram_clk"); @334
// &ModuleEnd; @335
endmodule