rtl/verilog/slave_reg.v

Fri, 13 Aug 2010 10:43:05 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 13 Aug 2010 10:43:05 +0100
changeset 0
11aef665a5d8
child 1
522426d22baa
permissions
-rw-r--r--

Initial commit, DMAC version 3.1

philpem@0 1 // =============================================================================
philpem@0 2 // COPYRIGHT NOTICE
philpem@0 3 // Copyright 2006 (c) Lattice Semiconductor Corporation
philpem@0 4 // ALL RIGHTS RESERVED
philpem@0 5 // This confidential and proprietary software may be used only as authorised by
philpem@0 6 // a licensing agreement from Lattice Semiconductor Corporation.
philpem@0 7 // The entire notice above must be reproduced on all authorized copies and
philpem@0 8 // copies may only be made to the extent permitted by a licensing agreement from
philpem@0 9 // Lattice Semiconductor Corporation.
philpem@0 10 //
philpem@0 11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
philpem@0 12 // 5555 NE Moore Court 408-826-6000 (other locations)
philpem@0 13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
philpem@0 14 // U.S.A email: techsupport@latticesemi.com
philpem@0 15 // =============================================================================/
philpem@0 16 // FILE DETAILS
philpem@0 17 // Project : LM32 DMA Component
philpem@0 18 // File : slave_reg.v
philpem@0 19 // Title : DMA Slave controller
philpem@0 20 // Dependencies : None
philpem@0 21 // Version : 7.0
philpem@0 22 // : Initial Release
philpem@0 23 // Version : 7.0SP2, 3.0
philpem@0 24 // 1. Read and Write channel of DMA controller are working in parallel,
philpem@0 25 // due to that now as soon as FIFO is not empty write channel of the DMA
philpem@0 26 // controller start writing data to the slave.
philpem@0 27 // 2. Burst Size supported by DMA controller is increased to support bigger
philpem@0 28 // burst (from current value of 4 and 8 to 16 and 32). Now 4 different type
philpem@0 29 // of burst sizes are supported by the DMA controller 4, 8, 16 and 32.
philpem@0 30 // For this Burst Size field of the control register is increased to 2 bits.
philpem@0 31 // 3. Glitch is removed on the S_ACK_O signal.
philpem@0 32 // Version : 3.1
philpem@0 33 // : Make DMA Engine compliant to Rule 3.100 of Wishbone Spec
philpem@0 34 // : which defines alignement of bytes in sub-word transfers.
philpem@0 35 // =============================================================================
philpem@0 36
philpem@0 37 `ifndef SLAVE_REG_FILE
philpem@0 38 `define SLAVE_REG_FILE
philpem@0 39 `include "system_conf.v"
philpem@0 40 module SLAVE_REG
philpem@0 41 #(parameter LENGTH_WIDTH = 16,
philpem@0 42 parameter FIFO_IMPLEMENTATION = "EBR")
philpem@0 43 (
philpem@0 44 //slave port
philpem@0 45 S_ADR_I, //32bits
philpem@0 46 S_DAT_I, //32bits
philpem@0 47 S_WE_I,
philpem@0 48 S_STB_I,
philpem@0 49 S_CYC_I,
philpem@0 50 S_CTI_I,
philpem@0 51 S_DAT_O, //32bits
philpem@0 52 S_ACK_O,
philpem@0 53 S_INT_O,
philpem@0 54 //Master Address
philpem@0 55 // MA_SEL_O,
philpem@0 56 // MB_SEL_O,
philpem@0 57 M_SEL_O,
philpem@0 58 //internal signals
philpem@0 59 reg_start,
philpem@0 60 reg_status,
philpem@0 61 reg_interrupt,
philpem@0 62 reg_busy,
philpem@0 63 data_length,
philpem@0 64 reg_cntlg,
philpem@0 65 reg_bt2,reg_bt1,reg_bt0,
philpem@0 66 incr_unit,
philpem@0 67 reg_s_con,
philpem@0 68 reg_d_con,
philpem@0 69 reg_00_data,
philpem@0 70 reg_04_data,
philpem@0 71 //system clock and reset
philpem@0 72 CLK_I,
philpem@0 73 RST_I
philpem@0 74 );
philpem@0 75
philpem@0 76 input [31:0] S_ADR_I;
philpem@0 77 input [31:0] S_DAT_I; //32bits
philpem@0 78 input S_WE_I;
philpem@0 79 input S_STB_I;
philpem@0 80 input S_CYC_I;
philpem@0 81 input [2:0] S_CTI_I;
philpem@0 82 output [31:0] S_DAT_O; //32bits
philpem@0 83 output S_ACK_O;
philpem@0 84 output S_INT_O; //interrupt signal
philpem@0 85 //Master Address
philpem@0 86 output [3:0] M_SEL_O;
philpem@0 87 // output [3:0] MA_SEL_O;
philpem@0 88 // output [3:0] MB_SEL_O;
philpem@0 89 //internal signals
philpem@0 90 output reg_start;
philpem@0 91 input reg_status;
philpem@0 92 input reg_interrupt;
philpem@0 93 input reg_busy;
philpem@0 94 output [LENGTH_WIDTH-1:0] data_length;
philpem@0 95 input reg_cntlg;
philpem@0 96 output reg_bt2,reg_bt1,reg_bt0;
philpem@0 97 output [2:0] incr_unit;
philpem@0 98 output reg_s_con;
philpem@0 99 output reg_d_con;
philpem@0 100 output [31:0] reg_00_data;
philpem@0 101 output [31:0] reg_04_data;
philpem@0 102
philpem@0 103 //system clock and reset
philpem@0 104 input CLK_I;
philpem@0 105 input RST_I;
philpem@0 106
philpem@0 107 parameter UDLY = 1;
philpem@0 108
philpem@0 109 reg [31:0] reg_00_data;
philpem@0 110 reg [31:0] reg_04_data;
philpem@0 111 reg [LENGTH_WIDTH-1:0] reg_08_data;
philpem@0 112 reg [6:0] reg_0c_data;
philpem@0 113
philpem@0 114 reg [3:0] M_SEL_O;
philpem@0 115 // wire [3:0] MA_SEL_O = M_SEL_O;
philpem@0 116 // wire [3:0] MB_SEL_O = M_SEL_O;
philpem@0 117 wire [LENGTH_WIDTH-1:0] data_length = reg_08_data;
philpem@0 118
philpem@0 119 wire reg_bt2, reg_bt1, reg_bt0, reg_incw, reg_inchw, reg_d_con, reg_s_con;
philpem@0 120 assign {reg_bt2,reg_bt1,reg_bt0,reg_incw,reg_inchw,reg_d_con,reg_s_con} = reg_0c_data;
philpem@0 121 wire [2:0] incr_unit = reg_incw ? 4 : reg_inchw ? 2 : 1;
philpem@0 122
philpem@0 123 wire [8:0] burst_incr_unit = reg_bt2 ? (reg_bt1 ? (reg_bt0 ? incr_unit<<5 : incr_unit<<4) : (reg_bt0 ? incr_unit<<3 : incr_unit<<2)) : incr_unit;
philpem@0 124 reg reg_ie;
philpem@0 125 wire [2:0] read_10_data = {reg_status,reg_ie,reg_busy};
philpem@0 126
philpem@0 127 wire reg_wr_rd = S_CYC_I && S_STB_I;
philpem@0 128
philpem@0 129 wire master_idle = !reg_busy;
philpem@0 130 reg s_ack_o_pre;
philpem@0 131 wire S_ACK_O = s_ack_o_pre && S_CYC_I && S_STB_I;
philpem@0 132
philpem@0 133 always @(posedge CLK_I or posedge RST_I)
philpem@0 134 if(RST_I)
philpem@0 135 s_ack_o_pre <= #UDLY 1'b0;
philpem@0 136 else if(((master_idle && reg_wr_rd) || (!master_idle && reg_wr_rd && !S_WE_I)) && (!s_ack_o_pre))
philpem@0 137 s_ack_o_pre <= #UDLY 1'b1;
philpem@0 138 else
philpem@0 139 s_ack_o_pre <= #UDLY 1'b0;
philpem@0 140
philpem@0 141
philpem@0 142 //register write and read
philpem@0 143 wire reg_wr = reg_wr_rd && S_WE_I && master_idle && S_ACK_O;
philpem@0 144 wire reg_rd = reg_wr_rd && !S_WE_I && S_ACK_O;
philpem@0 145
philpem@0 146 wire dw00_cs = (!(|S_ADR_I[5:2]));
philpem@0 147 wire dw04_cs = (S_ADR_I[5:2] == 4'h1);
philpem@0 148 wire dw08_cs = (S_ADR_I[5:2] == 4'h2);
philpem@0 149 wire dw0c_cs = (S_ADR_I[5:2] == 4'h3);
philpem@0 150 wire dw10_cs = (S_ADR_I[5:2] == 4'h4);
philpem@0 151
philpem@0 152 //S_DAT_O
philpem@0 153 wire [31:0] S_DAT_O = dw00_cs ? reg_00_data :
philpem@0 154 dw04_cs ? reg_04_data :
philpem@0 155 dw08_cs ? reg_08_data :
philpem@0 156 dw0c_cs ? {24'h0,1'h0,reg_0c_data} :
philpem@0 157 dw10_cs ? {24'h0,5'h0,read_10_data} : 32'h0;
philpem@0 158
philpem@0 159 always @(posedge CLK_I or posedge RST_I)
philpem@0 160 if(RST_I)
philpem@0 161 M_SEL_O <= #UDLY 4'h0;
philpem@0 162 else if(data_length < incr_unit)
philpem@0 163 case(data_length[2:0])
philpem@0 164 1: M_SEL_O <= #UDLY 4'h8;
philpem@0 165 2: M_SEL_O <= #UDLY 4'hc;
philpem@0 166 3: M_SEL_O <= #UDLY 4'he;
philpem@0 167 default:M_SEL_O <= #UDLY 4'hf;
philpem@0 168 endcase
philpem@0 169 else
philpem@0 170 case(incr_unit)
philpem@0 171 1: M_SEL_O <= #UDLY 4'h8;
philpem@0 172 2: M_SEL_O <= #UDLY 4'hc;
philpem@0 173 4: M_SEL_O <= #UDLY 4'hf;
philpem@0 174 default:M_SEL_O <= #UDLY 4'hf;
philpem@0 175 endcase
philpem@0 176 //interrupt
philpem@0 177 reg S_INT_O;
philpem@0 178 always @(posedge CLK_I or posedge RST_I)
philpem@0 179 if(RST_I)
philpem@0 180 S_INT_O <= #UDLY 1'b0;
philpem@0 181 else if(reg_interrupt && reg_ie)
philpem@0 182 S_INT_O <= #UDLY 1'b1;
philpem@0 183 else if(dw10_cs && reg_rd)
philpem@0 184 S_INT_O <= #UDLY 1'b0;
philpem@0 185
philpem@0 186 //reg_00
philpem@0 187 always @(posedge CLK_I or posedge RST_I)
philpem@0 188 if(RST_I)
philpem@0 189 reg_00_data <= #UDLY 32'h0;
philpem@0 190 else if(dw00_cs && reg_wr)
philpem@0 191 reg_00_data <= #UDLY S_DAT_I;
philpem@0 192
philpem@0 193 //reg_04
philpem@0 194 always @(posedge CLK_I or posedge RST_I)
philpem@0 195 if(RST_I)
philpem@0 196 reg_04_data <= #UDLY 32'h0;
philpem@0 197 else if(dw04_cs && reg_wr)
philpem@0 198 reg_04_data <= #UDLY S_DAT_I;
philpem@0 199
philpem@0 200 //reg_08
philpem@0 201 always @(posedge CLK_I or posedge RST_I)
philpem@0 202 if(RST_I)
philpem@0 203 reg_08_data <= #UDLY 32'h0;
philpem@0 204 else if(reg_cntlg)
philpem@0 205 reg_08_data <= #UDLY (reg_08_data < burst_incr_unit) ? 'h0 : (reg_08_data - burst_incr_unit);
philpem@0 206 else if(dw08_cs && reg_wr)
philpem@0 207 reg_08_data <= #UDLY S_DAT_I;
philpem@0 208
philpem@0 209 //reg_0c
philpem@0 210 always @(posedge CLK_I or posedge RST_I)
philpem@0 211 if(RST_I)
philpem@0 212 reg_0c_data <= #UDLY 7'h0;
philpem@0 213 else if(dw0c_cs && reg_wr)
philpem@0 214 reg_0c_data <= #UDLY S_DAT_I[6:0];
philpem@0 215
philpem@0 216 //reg_10
philpem@0 217 reg reg_start;
philpem@0 218 always @(posedge CLK_I or posedge RST_I)
philpem@0 219 if(RST_I)
philpem@0 220 begin
philpem@0 221 reg_ie <= #UDLY 1'b0;
philpem@0 222 reg_start <= #UDLY 1'b0;
philpem@0 223 end
philpem@0 224 else if(dw10_cs && reg_wr)
philpem@0 225 begin
philpem@0 226 reg_ie <= #UDLY S_DAT_I[1];
philpem@0 227 reg_start <= #UDLY S_DAT_I[3];
philpem@0 228 end
philpem@0 229 else
philpem@0 230 begin
philpem@0 231 reg_start <= #UDLY 1'b0;
philpem@0 232 end
philpem@0 233 endmodule // SLAVE_REG
philpem@0 234 `endif // SLAVE_REG_FILE