URL
https://opencores.org/ocsvn/wb_verilog/wb_verilog/trunk
Subversion Repositories wb_verilog
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 3 to Rev 4
- ↔ Reverse comparison
Rev 3 → Rev 4
/trunk/wb_master.v
0,0 → 1,299
// -*- Mode: Verilog -*- |
// Filename : wb_master.v |
// Description : Wishbone Master Behavorial |
// Author : Winefred Washington |
// Created On : Thu Jan 11 21:18:41 2001 |
// Last Modified By: . |
// Last Modified On: . |
// Update Count : 0 |
// Status : Unknown, Use with caution! |
|
// Description Specification |
// General Description: 8, 16, 32-bit WISHBONE Master |
// Supported cycles: MASTER, READ/WRITE |
// MASTER, BLOCK READ/WRITE |
// MASTER, RMW |
// Data port, size: 8, 16, 32-bit |
// Data port, granularity 8-bit |
// Data port, Max. operand size 32-bit |
// Data transfer ordering: little endian |
// Data transfer sequencing: undefined |
// |
|
module WB_MASTER32(CLK_I, RST_I, TAG_I, TAG_O, |
ACK_I, ADR_O, CYC_O, DAT_I, DAT_O, ERR_I, RTY_I, SEL_O, STB_O, WE_O); |
|
input CLK_I; |
input RST_I; |
input [3:0] TAG_I; |
output [3:0] TAG_O; |
input ACK_I; |
output [31:0] ADR_O; |
output CYC_O; |
input [31:0] DAT_I; |
output [31:0] DAT_O; |
input ERR_I; |
input RTY_I; |
output [3:0] SEL_O; |
output STB_O; |
output WE_O; |
|
reg [31:0] ADR_O; |
reg [3:0] SEL_O; |
reg CYC_O; |
reg STB_O; |
reg WE_O; |
reg [31:0] DAT_O; |
|
wire [15:0] mem_sizes; // determines the data width of an address range |
reg [31:0] write_burst_buffer[0:7]; |
reg [31:0] read_burst_buffer[0:7]; |
|
reg GO; |
integer cycle_end; |
integer address; |
integer data; |
integer selects; |
integer write_flag; |
|
// |
// mem_sizes determines the data widths of memory space |
// The memory space is divided into eight regions. Each |
// region is controlled by a two bit field. |
// |
// Bits |
// 00 = 8 bit memory space |
// 01 = 16 bit |
// 10 = 32 bit |
// 11 = 64 bit (not supported in this model |
// |
|
assign mem_sizes = 16'b00_01_10_11_00_01_10_11; |
|
function [1:0] data_width; |
input [31:0] adr; |
begin |
casex (adr[31:29]) |
3'b000: data_width = mem_sizes[15:14]; |
3'b001: data_width = mem_sizes[13:12]; |
3'b010: data_width = mem_sizes[11:10]; |
3'b011: data_width = mem_sizes[9:8]; |
3'b100: data_width = mem_sizes[7:6]; |
3'b101: data_width = mem_sizes[5:4]; |
3'b110: data_width = mem_sizes[3:2]; |
3'b111: data_width = mem_sizes[1:0]; |
3'bxxx: data_width = 2'bxx; |
endcase // casex (adr[31:29]) |
end |
endfunction |
|
always @(posedge CLK_I or posedge RST_I) |
begin |
if (RST_I) |
begin |
GO = 1'b0; |
end |
end |
|
// read single |
task rd; |
input [31:0] adr; |
output [31:0] result; |
|
begin |
cycle_end = 1; |
address = adr; |
selects = 255; |
write_flag = 0; |
|
GO <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
// wait for cycle to start |
while (~CYC_O) |
@(posedge CLK_I); |
|
// wait for cycle to end |
while (CYC_O) |
@(posedge CLK_I); |
|
result = data; |
|
end |
endtask // read |
|
task wr; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
begin |
cycle_end = 1; |
address = adr; |
selects = sel; |
write_flag = 1; |
data = dat; |
|
GO <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
// wait for cycle to start |
while (~CYC_O) |
@(posedge CLK_I); |
|
// wait for cycle to end |
while (CYC_O) |
@(posedge CLK_I); |
end |
endtask // wr |
|
// block read |
task blkrd; |
input [31:0] adr; |
input end_flag; |
output [31:0] result; |
|
begin |
write_flag = 0; |
cycle_end = end_flag; |
address = adr; |
GO <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
result = data; |
end |
endtask // blkrd |
|
// block write |
task blkwr; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
input end_flag; |
begin |
write_flag = 1; |
cycle_end = end_flag; |
address = adr; |
data = dat; |
selects = sel; |
GO <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
end |
endtask // blkwr |
|
// RMW |
task rmw; |
input [31:0] adr; |
input [31:0] dat; |
input [3:0] sel; |
output [31:0] result; |
|
begin |
// read phase |
write_flag = 0; |
cycle_end = 0; |
address = adr; |
GO <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
result = data; |
|
// write phase |
write_flag = 1; |
address = adr; |
selects = sel; |
GO <= 1; |
data <= dat; |
cycle_end <= 1; |
@(posedge CLK_I); |
GO <= 0; |
|
while (~(ACK_I & STB_O)) |
@(posedge CLK_I); |
|
end |
endtask // rmw |
|
always @(posedge CLK_I) |
begin |
if (RST_I) |
ADR_O <= 32'h0000_0000; |
else |
ADR_O <= address; |
end |
|
always @(posedge CLK_I) |
begin |
if (RST_I | ERR_I | RTY_I) |
CYC_O <= 1'b0; |
else if ((cycle_end == 1) & ACK_I) |
CYC_O <= 1'b0; |
else if (GO | CYC_O) |
CYC_O <= 1'b1; |
end |
|
// stb control |
always @(posedge CLK_I) |
begin |
if (RST_I | ERR_I | RTY_I) |
STB_O <= 1'b0; |
else if (STB_O & ACK_I) |
STB_O <= 1'b0; |
else if (GO | STB_O) |
STB_O <= 1'b1; |
end |
|
// selects & data |
always @(posedge CLK_I) |
begin |
if (write_flag == 0) begin |
SEL_O <= 4'b1111; |
if (STB_O & ACK_I) |
data <= DAT_I; |
end |
else begin |
case (data_width(address)) |
2'b00: begin |
SEL_O <= {3'b000, selects[0]}; |
DAT_O <= {data[7:0], data[7:0], data[7:0], data[7:0]}; |
end |
2'b01: begin |
SEL_O <= {2'b00, selects[1:0]}; |
DAT_O <= {data[15:0], data[15:0]}; |
end |
2'b10: begin |
SEL_O <= selects; |
DAT_O <= data; |
end |
endcase |
end |
end |
|
always @(posedge CLK_I) |
begin |
if (RST_I) |
WE_O <= 1'b0; |
else if (GO) |
WE_O <= write_flag; |
end |
|
endmodule |
|
|
|
|
|