总线读写---verilog代码
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: chensimin 5 // 6 // Create Date: 2017/11/16 17:32:35 7 // Design Name: 8 // Module Name: read_and_write 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 23 module read_and_write( 24 25 //-----------------------clock and reset-------------------------- 26 input wire clk, 27 input wire reset, 28 //-----------------------up_interface--------------------------- 29 input wire [11:0]up_address_channel, 30 input wire [31:0]up_wdata, 31 output wire [31:0]up_rdata, 32 input wire up_read_en, 33 input wire up_write_en, 34 output wire up_ack, 35 //--------------------device IPC interface------------------------ 36 input wire ipc_ack, 37 input wire [31:0]ipc_rdata, 38 output wire [31:0]ipc_wdata, 39 output wire ipc_rd, 40 output wire ipc_wr, 41 output wire [11:0]ipc_addr, 42 //--------------------------channel------------------------------- 43 input wire channel_sel, 44 //--------------------read flag----------------------------------- 45 output wire read_start_w 46 ); 47 48 49 //------------------------read------------------------------------ 50 reg ipc_rd_r; 51 reg [11:0]ipc_addr_r; 52 reg ipc_wr_r; 53 reg [31:0]ipc_wdata_r; 54 reg [31:0]ipc_rdata_r; 55 reg read_start; 56 reg read_done; 57 reg write_done; 58 reg [2:0]i; 59 reg [2:0]j; 60 reg get_read_address; 61 reg get_write_address; 62 reg up_read_en_delay; 63 reg up_write_en_delay; 64 65 always @ (posedge clk or posedge reset) 66 if(reset) 67 begin 68 up_read_en_delay <= 1'b0; 69 up_write_en_delay <= 1'b0; 70 end 71 else 72 begin 73 up_read_en_delay <= up_read_en; 74 up_write_en_delay <= up_write_en; 75 end 76 77 always @ (posedge clk or posedge reset) 78 if(reset) 79 begin 80 ipc_rd_r <= 1'b0; 81 ipc_rdata_r <= 32'h00000000; 82 read_start <= 1'b0; 83 read_done <= 1'b0; 84 i <= 3'd0; 85 get_read_address <= 1'b0; 86 end 87 else 88 begin 89 read_start <= 1'b0; 90 read_done <= 1'b0; 91 ipc_rd_r <= 1'b0; 92 get_read_address <= 1'b0; 93 case(i) 94 3'd0: 95 begin 96 if(channel_sel && up_read_en_delay) 97 begin 98 get_read_address <= 1'b1; 99 i <= i + 1'b1; 100 end 101 else 102 i <= 3'd0; 103 end 104 3'd1: 105 begin 106 if(!ipc_ack) 107 ipc_rd_r <= 1'b1; 108 else 109 begin 110 ipc_rdata_r <= ipc_rdata; 111 read_start <= 1'b1; 112 read_done <= 1'b1; 113 i <= i + 1'b1; 114 end 115 end 116 3'd2: 117 begin 118 if(channel_sel && !up_read_en_delay) 119 i <= 3'd0; 120 else 121 i <= 3'd2; 122 end 123 default: 124 begin 125 i <= 3'd0; 126 read_start <= 1'b0; 127 read_done <= 1'b0; 128 ipc_rd_r <= 1'b0; 129 get_read_address <= 1'b0; 130 end 131 endcase 132 end 133 //------------------------write-------------------------------- 134 always @ (posedge clk or posedge reset) 135 if(reset) 136 begin 137 ipc_wr_r <= 1'b0; 138 ipc_wdata_r <= 32'h00000000; 139 write_done <= 1'b0; 140 j <= 3'd0; 141 get_write_address <= 1'b0; 142 end 143 else 144 begin 145 write_done <= 1'b0; 146 ipc_wr_r <= 1'b0; 147 get_write_address <= 1'b0; 148 case(j) 149 3'd0: 150 begin 151 if(channel_sel && up_write_en_delay) 152 begin 153 get_write_address <= 1'b1; 154 ipc_wdata_r <= up_wdata; 155 j <= j + 1'b1; 156 end 157 else 158 j <= 3'd0; 159 end 160 3'd1: 161 begin 162 if(!ipc_ack) 163 ipc_wr_r <= 1'b1; 164 else 165 begin 166 write_done <= 1'b1; 167 j <= j + 1'b1; 168 end 169 end 170 3'd2: 171 begin 172 if(channel_sel && !up_write_en_delay) 173 j <= 3'd0; 174 else 175 j <= 3'd2; 176 end 177 default: 178 begin 179 j <= 3'd0; 180 write_done <= 1'b0; 181 ipc_wr_r <= 1'b0; 182 get_write_address <= 1'b0; 183 end 184 endcase 185 end 186 //-------------------up_ack signal-------------------------- 187 reg up_ack_r; 188 always @ (posedge clk or posedge reset) 189 if(reset) 190 up_ack_r <= 1'b0; 191 else if(read_done || write_done) 192 up_ack_r <= 1'b1; 193 else 194 up_ack_r <= 1'b0; 195 196 assign up_ack = up_ack_r; 197 198 //------------------drive addr output------------------------- 199 always @ (posedge clk or posedge reset) 200 if(reset) 201 ipc_addr_r <= 12'h000; 202 else if(get_read_address || get_write_address) 203 begin 204 ipc_addr_r <= up_address_channel; 205 end 206 207 assign ipc_rd = ipc_rd_r; 208 assign ipc_addr = ipc_addr_r; 209 assign ipc_wdata = ipc_wdata_r; 210 assign ipc_wr = ipc_wr_r; 211 assign up_rdata = ipc_rdata_r; 212 assign read_start_w = read_start; 213 214 endmodule
备注:在进行总线写操作的时候,写地址和数据信号要先准备好,等待写使能信号的到来。
非常重要的两点需要注意:
1.外部输入的控制信号,(如使能信号)往往和clk不同步,这就需要在使用前做延时处理,使其同步,这需要根据调试情况来定。
2.使能信号的使用,使能信号往往是一种脉冲信号,即:一个高点平期间,只进行一次相应的操作(读或写),这就需要在状态机中对使能信号进行合理的运用。如状态机中最后的一个状态:
1 3'd2: 2 begin 3 if(channel_sel && !up_read_en_delay) 4 i <= 3'd0; 5 else 6 i <= 3'd2; 7 end 8 9 3'd2: 10 begin 11 if(channel_sel && !up_write_en_delay) 12 j <= 3'd0; 13 else 14 j <= 3'd2; 15 end
当使能信号执行完一个状态机后拉低时,状态机回到初始状态;
当使能信号执行完一个状态机后依旧保持高电平,状态机依旧保持当前状态。
这就是一个使能脉冲,执行一次操作的控制方法。