V3学院老凯

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

1.数据源一张bmp图片用read_bmp.exe 读取此图片此图片命名为sobel.bmp,生成文本格式的图像信息bmp_dat.txt,注意只支持bmp8位图。

2.把此文本信息拷贝到verilog仿真目录下边。

3.运行仿真产生处理后的post_process_dat.txt图像文本信息。

4.运行bmp_process.exe 处理post_process_dat.txt文本信息补充信息。产生post_dat1.txt

5.再运行 bmp_bin.exe 处理post_dat1.txt 并产生结果图像。

bin文件处理下载

前几天有位朋友对 此代码有兴趣现放出来给大家共享!

顶层模块sobel

 

 

compute
`timescale 1ns/1ns

module compute(
//输入信号
clk_i,
dat_i,//数据总线
shift_en,//移位寄存器使能信号
prev_row_load,//加载前一行数据到寄存器
curr_row_load,//加载当前行数据到寄存器
next_row_load,//加载下一行数据到寄存器
//输出
result_row //运算结果输出
);

input clk_i;
input[31:0] dat_i;
input shift_en;
input prev_row_load;
input curr_row_load;
input next_row_load;
output[31:0] result_row ;

//计算数据通路信号

reg [31:0] prev_row, curr_row, next_row;
reg [7:0] O[-1:1][-1:1];
reg signed [10:0] Dx, Dy;
//wire signed [10:0] D;
reg [7:0] abs_D;
reg [31:0] result_row;

//可进行计算的数据通路

always@(posedge clk_i) //上一行寄存器
if(prev_row_load)
prev_row <= dat_i;
else
if(shift_en)
prev_row[31:8] <= prev_row[23:0];

always@(posedge clk_i) //当前行寄存器
if(curr_row_load)
curr_row<= dat_i;
else
if(shift_en )
curr_row [31:8]<=curr_row[23:0];

always@(posedge clk_i) //下一行寄存器
if(next_row_load)
next_row<=dat_i;
else
if(shift_en )
next_row [31:8]<=next_row[23:0];

//计算绝对值函数

function [10:0] abs ( input signed [10:0] x);
abs = x >=0 ? x : -x ;
endfunction

//计算流水线
//assign D = abs(Dx) + abs(Dy);
always @(posedge clk_i)
if ( shift_en ) begin
//D = abs(Dx) + abs(Dy);
abs_D <= (abs(Dx) + abs(Dy))>>3 ;
// abs_D <= D[10:3];
Dx <= -$signed({3'b000, O[-1][-1]}) //-1* O[-1][-1]
+$signed({3'b000, O[-1][+1]}) //+1* O[-1][+1]
-($signed({3'b000, O[ 0][-1]}) //-2* O[ 0][-1]
<<1)

+($signed({3'b000, O[ 0][+1]}) //+2* O[ 0][+1]
<<1)

-$signed({3'b000, O[+1][-1]}) //-1* O[+1][-1]
+$signed({3'b000, O[+1][+1]}); //+1* O[+1][+1]
Dy <= $signed({3'b000, O[-1][-1]}) //+1* O[-1][-1]
+($signed({3'b000, O[-1][ 0]}) //+2* O[-1][0]
<<1)

+$signed({3'b000, O[-1][+1]}) //+1* O[-1][+1]
-$signed({3'b000, O[+1][-1]})//-1* O[+1][-1]
-($signed({3'b000, O[+1][ 0]}) //-2* O[+1][ 0]
<<1)

-$signed({3'b000, O[+1][+1]}); //-1* O[+1][+1]
O[-1][-1] <= O[-1][0];
O[-1][ 0] <= O[-1][+1];
O[-1][+1] <= prev_row[31:24];
O[ 0][-1] <= O[0][0];
O[ 0][ 0] <= O[0][+1];
O[ 0][+1] <= curr_row[31:24];
O[+1][-1] <= O[+1][0];
O[+1][ 0] <= O[+1][+1];
O[+1][+1] <= next_row[31:24];
end

always @(posedge clk_i) //结果行寄存器
if(shift_en)
result_row <= { result_row[23:0],abs_D };

endmodule

 

machine
`timescale 1ns/1ns

module machine(
//输入
clk_i,
rst_i,
ack_i,
start,
//输出

offset_reset,
O_offset_cnt_en,
D_offset_cnt_en,
prev_row_load,
curr_row_load,
next_row_load,
shift_en,
cyc_o,
we_o,
stb_o,
current_state,
done_set
);
input clk_i;
input rst_i;
input ack_i;
input start;
output offset_reset;
output O_offset_cnt_en;
output D_offset_cnt_en;
output prev_row_load;
output curr_row_load;
output next_row_load;
output shift_en;
output cyc_o;
output we_o;
output stb_o;
output[4:0] current_state;
output done_set; //一幅图像处理完标志

parameter WIDTH = 640;
parameter HEIGHT = 480;

parameter [4:0] idle =5'b00000,
read_prev_0 =5'b00001,
read_curr_0 =5'b00010,
read_next_0 =5'b00011,
comp1_0 =5'b00100,
comp2_0 =5'b00101,
comp3_0 =5'b00110,
comp4_0 =5'b00111,
read_prev =5'b01000,
read_curr =5'b01001,
read_next =5'b01010,
comp1 =5'b01011,
comp2 =5'b01100,
comp3 =5'b01101,
comp4 =5'b01110,
write_result =5'b01111,
write_158 =5'b10000,
comp1_159 =5'b10001,
comp2_159 =5'b10010,
comp3_159 =5'b10011,
comp4_159 =5'b10100,
write_159 =5'b10101;

reg [4:0] current_state,next_state;
reg [8:0] row; //范围从 0 到 477;
reg [7:0] col; //范围从0 到 159;

wire start;
wire stb_o;
reg offset_reset,row_reset,col_reset;

reg prev_row_load, curr_row_load, next_row_load;
reg shift_en;
reg cyc_o,we_o;
reg row_cnt_en, col_cnt_en;
reg O_offset_cnt_en, D_offset_cnt_en;
reg int_en, done_set, done;

//控制部分用于确定行列计算过程的两个计数器,分别用下面两个always块表示:

always @(posedge clk_i) //Row counter
if (row_reset)
row <= 0;
else
if (row_cnt_en)
row <= row + 1;

always @(posedge clk_i) //Column counter
if (col_reset)
col <= 0;
else
if (col_cnt_en)
col<= col+1;

//有限状态机
always @(posedge clk_i) //State register
if (rst_i)
current_state<= idle;
else
current_state<= next_state;

always @*
begin //FSM 的组合逻辑部分
offset_reset =1'b0;
row_reset =1'b0;
col_reset =1'b0;
row_cnt_en =1'b0;
col_cnt_en =1'b0;
O_offset_cnt_en =1'b0;
D_offset_cnt_en =1'b0;
prev_row_load =1'b0;
curr_row_load =1'b0;
next_row_load =1'b0;
shift_en =1'b0;
cyc_o =1'b0;
we_o =1'b0;
done_set =1'b0;

case (current_state)
idle: begin
cyc_o =1'b0;
we_o =1'b0;
done_set=1'b0;
D_offset_cnt_en =1'b0;
offset_reset =1'b1;
row_reset =1'b1;
col_reset = 1'b1;
if (start)
next_state = read_prev_0;
else
next_state = idle;
end
read_prev_0: begin
offset_reset =1'b0;
row_reset =1'b0;
we_o =1'b0;
row_cnt_en =1'b0;
D_offset_cnt_en =1'b0;
col_reset = 1'b1;
prev_row_load = 1'b1;
cyc_o = 1'b1;
if (ack_i)
next_state = read_curr_0;
else
next_state = read_prev_0;
end
read_curr_0: begin
col_reset = 1'b0;
prev_row_load = 1'b0;
curr_row_load =1'b1;
cyc_o =1'b1;
if (ack_i)
next_state = read_next_0;
else
next_state = read_curr_0;
end
read_next_0: begin
curr_row_load =1'b0;
next_row_load =1'b1;
cyc_o =1'b1;
if (ack_i)
begin
O_offset_cnt_en =1'b1;
next_state =comp1_0;
end
else
next_state = read_next_0;
end
comp1_0: begin
next_row_load =1'b0;
cyc_o =1'b0;
O_offset_cnt_en =1'b0;
shift_en =1'b1;
next_state =comp2_0;
end
comp2_0: begin
shift_en =1'b1;
next_state =comp3_0;
end
comp3_0: begin
shift_en =1'b1;
next_state =comp4_0;
end
comp4_0: begin
shift_en =1'b1;
next_state =read_prev;
end
read_prev: begin
shift_en =1'b0;
we_o =1'b0;
col_cnt_en =1'b0;
D_offset_cnt_en =1'b0;
prev_row_load = 1'b1;
cyc_o = 1'b1;
if (ack_i)
next_state = read_curr;
else
next_state = read_prev;
end
read_curr: begin
prev_row_load = 1'b0;
curr_row_load = 1'b1;
cyc_o = 1'b1;
if (ack_i)
next_state = read_next;
else
next_state = read_curr;
end
read_next: begin
curr_row_load = 1'b0;
next_row_load =1'b1;
cyc_o = 1'b1;
if (ack_i)
begin
O_offset_cnt_en =1'b1;
next_state = comp1;
end
else
next_state = read_next;
end
comp1: begin
next_row_load =1'b0;
O_offset_cnt_en =1'b0;
cyc_o =1'b0;
shift_en =1'b1;
next_state =comp2;
end
comp2: begin
shift_en =1'b1;
next_state =comp3;
end
comp3: begin
shift_en =1'b1;
next_state =comp4;
end
comp4: begin
shift_en =1'b1;
if (col ==(WIDTH/4-2))
next_state = write_158;
else
next_state = write_result;
end
write_result: begin
shift_en =1'b0;
cyc_o =1'b1;
we_o =1'b1;
if(ack_i)
begin
col_cnt_en =1'b1;
D_offset_cnt_en =1'b1;
next_state =read_prev;
end
else
next_state = write_result;
end
write_158: begin
shift_en =1'b0;
cyc_o =1'b1;
we_o =1'b1;
if(ack_i)
begin
col_cnt_en =1'b1;
D_offset_cnt_en =1'b1;
next_state =comp1_159;
end
else
next_state =write_158;
end
comp1_159: begin
col_cnt_en =1'b0;
D_offset_cnt_en =1'b0;
cyc_o =1'b0;
we_o =1'b0;
shift_en =1'b1;
next_state =comp2_159;
end
comp2_159: begin
shift_en =1'b1;
next_state =comp3_159;
end
comp3_159: begin
shift_en =1'b1;
next_state =comp4_159;
end
comp4_159: begin
shift_en =1'b1;
next_state =write_159;
end
write_159: begin
shift_en =1'b0;
cyc_o =1'b1;
we_o =1'b1;
if(ack_i)
begin
D_offset_cnt_en =1'b1;
if (row == HEIGHT-3) //一幅图像处理完
begin
done_set =1'b1;
next_state = idle;
end
else
begin
row_cnt_en =1'b1;
next_state =read_prev_0;
end
end
else
next_state = write_159;
end
endcase
end


assign stb_o = cyc_o;

endmodule
sobel_slave
`timescale 1ns/1ns
module sobel_slave(
//主从接口共用信号
clk_i,
rst_i,
dat_i,
dat_o,
//从机接口信号
cyc_i,
stb_i,
we_i,
adr_i,
ack_o,
//输出信号
start,
O_base_ce,
D_base_ce,

int_req,//中断申请

//输入信号
done_set,
result_row
);

input clk_i;
input rst_i;
input[31:0] dat_i;
output[31:0] dat_o;

input cyc_i;
input stb_i;
input we_i;
input[21:0] adr_i;
output ack_o;
output start;
output O_base_ce;
output D_base_ce;
output int_req;
input done_set;
input[31:0] result_row;

reg int_en;
reg done;
reg ack_o;
reg[31:0] dat_o ;

assign start = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b01;//adr_i[3:2]

assign O_base_ce = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b10;

assign D_base_ce = cyc_i && stb_i && we_i && adr_i[3:2] ==2'b11;

// Wishbone 从机接口

always @(posedge clk_i) // 中断使能寄存器
if (rst_i)
int_en <= 1'b0;
else if (cyc_i && stb_i && we_i && adr_i[3:2] ==2'b00)
int_en <= dat_i[0];

always @(posedge clk_i) // 状态寄存器
if (rst_i)
done <=1'b0;
else
if (done_set)
// This occurs when last write is acknowledged,
// and so cannot coincide with a read of the
// status register
done <=1'b1;
else
if (cyc_i && stb_i && !we_i && adr_i[3:2] ==2'b00 && ack_o)
done <=1'b0;//应该为读操作
//中断申请
assign int_req =int_en && done;

always @(posedge clk_i) // 生成应答ack输出
ack_o <= cyc_i && stb_i && !ack_o;

//总线数据输出多路选择器

always @*
if (cyc_i && stb_i && !we_i)
if (adr_i[3:2] == 2'b00)
dat_o = {31'b0,done}; // status register read
else
dat_o = 32'b0; // other registers read as 0
else
dat_o = result_row; // for master write

endmodule
addr_gen
`timescale 1ns/1ns
module addr_gen(
//输入
clk_i,
dat_i,//数据总线
O_base_ce,//锁存原始图像的基地址
D_base_ce,//锁存导数图像的基地址
O_offset_cnt_en,//原始图像地址偏移量计数器使能信号
D_offset_cnt_en,//导数图像地址偏移量计数器使能信号
offset_reset,//地址偏移量计数器复位信号
prev_row_load,
curr_row_load,
next_row_load,
//输出
adr_o
);
input clk_i;
input[31:0] dat_i;
input O_base_ce;
input D_base_ce;
input O_offset_cnt_en;
input D_offset_cnt_en;
input offset_reset ;
input prev_row_load;
input curr_row_load;
input next_row_load;
output[21:0] adr_o ;

parameter WIDTH = 640;

reg[19:0] O_base ;
reg[19:0] D_base ;
reg[16:0] O_offset;
reg[16:0] D_offset;
wire[19:0] O_prev_addr;
wire[19:0] O_curr_addr;
wire[19:0] O_next_addr;
wire[19:0] D_addr;
always @(posedge clk_i) // O基地址寄存器
if(O_base_ce)
O_base <= dat_i[21:2];

always @(posedge clk_i) // O 地址偏移量计数器
if(offset_reset)
O_offset <= 0;
else
if(O_offset_cnt_en)
O_offset <= O_offset+1;

assign O_prev_addr = O_base + O_offset;
assign O_curr_addr = O_prev_addr + WIDTH/4;
assign O_next_addr = O_prev_addr + 2*WIDTH/4;

always @(posedge clk_i) // D基地址寄存器
if(D_base_ce)
D_base <=dat_i[21:2];

always @(posedge clk_i) // D地址偏移量计数器
if(offset_reset)
D_offset <= 0;
else
if(D_offset_cnt_en)
D_offset <= D_offset+1;

assign D_addr = D_base +D_offset;

assign adr_o[21:2] = prev_row_load ? O_prev_addr :
curr_row_load ? O_curr_addr :
next_row_load ? O_next_addr :
D_addr;
assign adr_o[1:0] = 2'b00;

endmodule
cpu
`timescale 1ns/1ns
module cpu(
clk_i,
rst_i,
cpu_ack_i,
cpu_cyc_o,
cpu_stb_o,
cpu_we_o,
cpu_adr_o,
cpu_dat_i,
cpu_dat_o
);

input clk_i;
input rst_i;
input cpu_ack_i;
output cpu_cyc_o;
output cpu_stb_o;
output cpu_we_o;
output[22:0] cpu_adr_o;
input[31:0] cpu_dat_i;
output[31:0] cpu_dat_o;

parameter [22:0] mem_base = 23'h000000;
parameter [22:0] sobel_reg_base = 23'h400000;
parameter sobel_int_reg_offset = 0;
parameter sobel_start_reg_offset = 4;
parameter sobel_O_base_reg_offset = 8;
parameter sobel_D_base_reg_offset = 12;
parameter sobel_status_reg_offset = 0;

reg cpu_cyc_o, cpu_stb_o, cpu_we_o;
reg [3:0] cpu_sel_o;///////////////////////////
reg [22:0] cpu_adr_o;
wire cpu_ack_i;
reg [31:0] cpu_dat_o;
wire[31:0] cpu_dat_i;

task bus_write ( input [22:0] adr, input [31:0] dat );
begin
cpu_adr_o = adr;
cpu_sel_o = 4'b1111;
cpu_dat_o = dat;
cpu_cyc_o = 1'b1;
cpu_stb_o = 1'b1;
cpu_we_o = 1'b1;
@(posedge clk_i);
while (!cpu_ack_i)
@(posedge clk_i);
end
endtask

initial begin // 处理器总线功能模型
cpu_adr_o = 23'h000000;
cpu_sel_o = 4'b0000;

cpu_dat_o = 32'h00000000;
cpu_cyc_o = 1'b0;
cpu_stb_o = 1'b0;
cpu_we_o = 1'b0;
@(negedge rst_i);
@(posedge clk_i);
// 把008000 (hex)写到 O_base_addr寄存器
bus_write(sobel_reg_base
+ sobel_O_base_reg_offset, 32'h00008000);
// 把053000 + 280(hex) 写到 D_base_addr register
bus_write(sobel_reg_base
+ sobel_D_base_reg_offset, 32'h00053280);
// 把1写到中断控制寄存器 (中断使能)
bus_write(sobel_reg_base
+ sobel_int_reg_offset, 32'h00000001);
//写到启动寄存器 (不考虑数据值)
bus_write(sobel_reg_base
+ sobel_start_reg_offset, 32'h00000000);
//写操作的结束
cpu_cyc_o = 1'b0;
cpu_stb_o = 1'b0;
cpu_we_o = 1'b0;

begin: loop
forever begin
#10000;
@(posedge clk_i);
//读取状态寄存器
cpu_adr_o = sobel_reg_base + sobel_status_reg_offset;
cpu_sel_o = 4'b1111;
cpu_cyc_o = 1'b1;
cpu_stb_o = 1'b1;
cpu_we_o = 1'b0;
@(posedge clk_i);
while (!cpu_ack_i)
@( posedge clk_i);
cpu_cyc_o = 1'b0;
cpu_stb_o = 1'b0;
cpu_we_o = 1'b0;
if(cpu_dat_i[0])
disable loop;
end
end
end

endmodule
memory
//bmp图像数据路径
`define bmp_data_file "./bmp_dat.txt"

`timescale 1ns/1ns
module memory(
clk_i,
mem_cyc_i,
mem_stb_i,
mem_we_i,
mem_ack_o,
mem_adr_i,
mem_dat_i,
mem_dat_o
);

input clk_i;
input mem_cyc_i;
input mem_stb_i;
input mem_we_i;
output mem_ack_o ;

input[21:0] mem_adr_i;
input[31:0] mem_dat_i ;
output[31:0] mem_dat_o;
wire mem_stb_i;
integer DATAFILE;
reg mem_ack_o;
reg [31:0] mem_dat_o;
reg[7:0] mem['h53000-1:'h8000];//存储原始图像数据,地址从8000H-53000H

initial
DATAFILE =$fopen("post_process_dat.txt");//打开文件,用于存储经sobel处理过的数据

initial
$readmemh(`bmp_data_file,mem);//原始图像数据读到memory中
always begin // 存储器总线功能模型
mem_ack_o = 1'b0;
mem_dat_o = 32'h00000000;
@(posedge clk_i);
//while (!(bus_cyc && mem_stb_i)) @(posedge clk);
while (!(mem_cyc_i && mem_stb_i)) @(posedge clk_i);
//if (!bus_we)
if (!mem_we_i)
mem_dat_o ={mem[mem_adr_i],mem[mem_adr_i+1],mem[mem_adr_i+2],mem[mem_adr_i+3]}; //数据组成4个字节输出

else if($time) //time=0时程序会写4个x到文件中,而这是不需要的
begin//sobel把处理完数据写到memory
//$display("current time is %t",$time); //打印什么时间的数据被写到文件中
$fdisplay(DATAFILE,"%0h",mem_dat_i[31:24]);
$fdisplay(DATAFILE,"%0h",mem_dat_i[23:16]);
$fdisplay(DATAFILE,"%0h",mem_dat_i[15:8]);
$fdisplay(DATAFILE,"%0h",mem_dat_i[7:0]);
end
mem_ack_o = 1'b1;
@(posedge clk_i);

end

endmodule
sobel
`timescale 1ns/1ns
module sobel (
//主从接口共用信号
clk_i,
rst_i,
dat_i,
dat_o,
//主机接口信号
cyc_o,
stb_o,
we_o,
adr_o,
ack_i,
//从机接口信号
cyc_i,
stb_i,
we_i,
adr_i,
ack_o,
//输出信号
prev_row_load,
curr_row_load,
next_row_load,
current_state,
int_req//中断申请

);

input clk_i;
input rst_i;
input[31:0] dat_i;
output[31:0] dat_o;
output cyc_o;
output stb_o;
output we_o;
output[21:0] adr_o;
input ack_i;
input cyc_i;
input stb_i;
input we_i;
input[21:0] adr_i;
output ack_o;
output prev_row_load;
output curr_row_load;
output next_row_load;
output[4:0] current_state;
output int_req;

wire start;
wire ack_i;
wire cyc_o;
wire stb_o;
wire we_o;
wire O_base_ce;
wire D_base_ce;
wire done_set;
wire shift_en;
wire prev_row_load;
wire curr_row_load;
wire next_row_load;
wire O_offset_cnt_en;
wire D_offset_cnt_en;
wire offset_reset;
wire[31:0] result_row;
wire[31:0] dat_i;
wire[21:0] adr_o;
wire ack_o;
wire[31:0] dat_o ;

wire[4:0] current_state;
//模块实例化

compute compute(.clk_i(clk_i),
.dat_i(dat_i),
.shift_en(shift_en),
.prev_row_load(prev_row_load),
.curr_row_load(curr_row_load),
.next_row_load(next_row_load),
.result_row(result_row)
);

addr_gen addr_gen(
.clk_i(clk_i),
.dat_i(dat_i),
.O_base_ce(O_base_ce),
.D_base_ce(D_base_ce),
.O_offset_cnt_en(O_offset_cnt_en),
.D_offset_cnt_en(D_offset_cnt_en),
.offset_reset(offset_reset),
.prev_row_load(prev_row_load),
.curr_row_load(curr_row_load),
.next_row_load(next_row_load),
.adr_o(adr_o)
);
machine machine(
.clk_i(clk_i),
.rst_i(rst_i),
.ack_i(ack_i),
.start(start),
.offset_reset(offset_reset),
.O_offset_cnt_en(O_offset_cnt_en),
.D_offset_cnt_en(D_offset_cnt_en),
.prev_row_load(prev_row_load),
.curr_row_load(curr_row_load),
.next_row_load(next_row_load),
.shift_en(shift_en),
.cyc_o(cyc_o),
.we_o(we_o),
.stb_o(stb_o),
.current_state(current_state),
.done_set(done_set)
);
sobel_slave sobel_slave(
.clk_i(clk_i),
.rst_i(rst_i),
.dat_i(dat_i),
.dat_o(dat_o),
.cyc_i(cyc_i),
.stb_i(stb_i),
.we_i(we_i),
.adr_i(adr_i),
.ack_o(ack_o),
.start(start),
.O_base_ce(O_base_ce),
.D_base_ce(D_base_ce),
.int_req(int_req),
.done_set(done_set),
.result_row(result_row)
);
endmodule
testbench
`timescale 1ns/1ns

`define width 500 //bmp原图实际宽度
`define height 213 //bmp原图高度

module testbench;

parameter t_c = 10;
parameter [22:0] mem_base = 23'h000000;
parameter [22:0] sobel_reg_base = 23'h400000;
parameter sobel_int_reg_offset = 0;
parameter sobel_start_reg_offset = 4;
parameter sobel_O_base_reg_offset = 8;
parameter sobel_D_base_reg_offset = 12;
parameter sobel_status_reg_offsed = 0;

reg clk, rst;
reg[(12*8):0] curr_state;
reg[(5*8):0] arbiter_curr_state;
wire bus_cyc, bus_stb, bus_we, bus_ack;
//wire [3:0] bus_sel;
wire [22:0] bus_adr;
wire [31:0] bus_dat;
wire int_req;
wire sobel_sel, mem_sel;
wire sobel_cyc_o, sobel_stb_o, sobel_we_o;
wire [21:0] sobel_adr_o;
wire sobel_ack_i;
wire sobel_stb_i;
wire sobel_ack_o;
wire sobel_gnt;
wire [31:0] sobel_dat_o;
wire cpu_cyc_o, cpu_stb_o, cpu_we_o;
wire [22:0] cpu_adr_o;
wire cpu_ack_i;
wire [31:0] cpu_dat_o;
wire cpu_gnt;
wire mem_ack_o;
wire [31:0] mem_dat_o;

wire prev_row_load;
wire curr_row_load;
wire next_row_load;
wire[4:0] current_state;
wire arbiter_current_state;

initial
begin
$fsdbDumpfile("wave_test.fsdb"); //文件名随便起
$fsdbDumpvars;
end



always begin // 时钟发生器
clk = 1'b1; #(t_c/2);
clk = 1'b0; #(t_c/2);
end

initial begin // 复位发生器
rst = 1'b1;
#(2.5*t_c) rst = 1'b0;
@(posedge int_req);
$stop;//一幅图像处理完结束仿真
end


// 总线主机多路选择器和逻辑

assign bus_cyc = sobel_gnt ? sobel_cyc_o : cpu_cyc_o;
assign bus_stb = sobel_gnt ? sobel_stb_o : cpu_stb_o;
assign bus_we = sobel_gnt ? sobel_we_o : cpu_we_o;

//assign bus_sel = sobel_gnt ? 4'b1111 : cpu_sel_o;

assign bus_adr = sobel_gnt ? {1'b0, sobel_adr_o}:cpu_adr_o;

assign sobel_ack_i = bus_ack & sobel_gnt;
assign cpu_ack_i = bus_ack & cpu_gnt;

// 总线从机逻辑

assign sobel_sel = (bus_adr & 23'h7FFFF0) == sobel_reg_base;//选中作为从机
assign mem_sel = (bus_adr & 23'h400000) == mem_base;//选中作为从机

assign sobel_stb_i = bus_stb & sobel_sel;
assign mem_stb_i = bus_stb & mem_sel;
assign sobel_cyc_i =bus_cyc&sobel_sel;
assign mem_cyc_i =bus_cyc&mem_sel;

assign bus_ack = sobel_sel ? sobel_ack_o :
mem_sel ? mem_ack_o:
1'b0;
initial
$strobe("width is %0d,height is %0d",`width,`height);

// 总线数据多路选择器
assign bus_dat = sobel_gnt && bus_we || sobel_sel && !bus_we
? sobel_dat_o :
cpu_gnt && bus_we
? cpu_dat_o :
mem_dat_o;


always@(arbiter_current_state)
case(arbiter_current_state)
1'b0:arbiter_curr_state="sobel";
1'b1:arbiter_curr_state="cpu";
endcase

always@(current_state)
case(current_state)
5'h0: curr_state="idle";
5'h1: curr_state="read_prev_0";
5'h2: curr_state="read_curr_0";
5'h3: curr_state="read_next_0";
5'h4: curr_state="comp1_0";
5'h5: curr_state="comp2_0";
5'h6: curr_state="comp3_0";
5'h7: curr_state="comp4_0";
5'h8: curr_state="read_prev";
5'h9: curr_state="read_curr";
5'ha: curr_state="read_next";
5'hb: curr_state="comp1";
5'hc: curr_state="comp2";
5'hd: curr_state="comp3";
5'he: curr_state="comp4";
5'hf: curr_state="write_result";
5'h10: curr_state="write_158";
5'h11: curr_state="comp1_159";
5'h12: curr_state="comp2_159";
5'h13: curr_state="comp3_159";
5'h14: curr_state="comp4_159";
5'h15: curr_state="write_159";
default:curr_state="???";
endcase

sobel duv (
.clk_i(clk),
.rst_i(rst),
.cyc_o(sobel_cyc_o),
.stb_o(sobel_stb_o),
.we_o (sobel_we_o),
.adr_o(sobel_adr_o),
.ack_i(sobel_ack_i),
.cyc_i(sobel_cyc_i),
.stb_i(sobel_stb_i),
.we_i(bus_we),
.adr_i(bus_adr[21:0]),
.ack_o(sobel_ack_o),
.dat_o(sobel_dat_o),
.dat_i(bus_dat),
.prev_row_load(prev_row_load),
.curr_row_load(curr_row_load),
.next_row_load(next_row_load),
.current_state(current_state),
.int_req(int_req)
);
defparam duv.machine.WIDTH = `width,
duv.machine.HEIGHT = `height,
duv.addr_gen.WIDTH = `width;


cpu cpu (
.clk_i(clk),
.rst_i(rst),
.cpu_ack_i(cpu_ack_i),
.cpu_cyc_o(cpu_cyc_o),
.cpu_stb_o(cpu_stb_o),
.cpu_we_o(cpu_we_o),
.cpu_adr_o(cpu_adr_o),
.cpu_dat_i(bus_dat),
.cpu_dat_o(cpu_dat_o)
);

memory memory(
.clk_i(clk),
.mem_cyc_i(mem_cyc_i),
.mem_stb_i(mem_stb_i),
.mem_we_i(bus_we),
.mem_ack_o(mem_ack_o),
.mem_adr_i(bus_adr[21:0]),
.mem_dat_i(bus_dat),
.mem_dat_o(mem_dat_o)
);

arbiter arbiter(
.clk_i(clk),
.rst_i(rst),
.sobel_cyc_i(sobel_cyc_o),
.cpu_cyc_i(cpu_cyc_o),
.sobel_gnt(sobel_gnt),
.cpu_gnt(cpu_gnt),
.arbiter_current_state(arbiter_current_state)
);

endmodule

test.do

View Code
vlib work
vmap work work
vlog addr_gen.v
vlog arbiter.v
vlog compute.v
vlog cpu.v
vlog machine.v
vlog memory.v
vlog sobel.v
vlog sobel_slave.v
vlog testbench.v
vsim -c work.testbench
run -all
quit -f
View Code
 1 `timescale 1ns/1ns
2 module arbiter(
3 clk_i,
4 rst_i,
5 sobel_cyc_i,
6 cpu_cyc_i,
7 sobel_gnt,
8 cpu_gnt,
9 arbiter_current_state
10 );
11 input clk_i;
12 input rst_i;
13 input sobel_cyc_i;
14 input cpu_cyc_i;
15 output sobel_gnt;
16 output cpu_gnt;
17 output arbiter_current_state;
18
19 parameter sobel = 1'b0, cpu =1'b1;
20 reg arbiter_current_state, arbiter_next_state;
21
22 reg sobel_gnt, cpu_gnt;
23
24 always @(posedge clk_i) // 仲裁器有限状态机寄存器
25 if (rst_i)
26 arbiter_current_state <= sobel;
27 else
28 arbiter_current_state <= arbiter_next_state;
29
30 always @* // 仲裁器逻辑
31 case (arbiter_current_state)
32 sobel: if (sobel_cyc_i) begin
33 sobel_gnt <= 1'b1;
34 cpu_gnt <= 1'b0;
35 arbiter_next_state <= sobel;
36 end
37 else
38 if (!sobel_cyc_i && cpu_cyc_i) begin
39 sobel_gnt <= 1'b0;
40 cpu_gnt <= 1'b1;
41 arbiter_next_state <= cpu;
42 end
43 else begin
44 sobel_gnt <= 1'b0;
45 cpu_gnt <= 1'b0;
46 arbiter_next_state <= sobel;
47 end
48 cpu: if (cpu_cyc_i) begin
49 sobel_gnt <= 1'b0;
50 cpu_gnt <= 1'b1;
51 arbiter_next_state <= cpu;
52 end
53 else
54 if (sobel_cyc_i && !cpu_cyc_i) begin
55 sobel_gnt <= 1'b1;
56 cpu_gnt <= 1'b0;
57 arbiter_next_state <= sobel;
58 end
59 else begin
60 sobel_gnt <= 1'b0;
61 cpu_gnt <= 1'b0;
62 arbiter_next_state <= sobel;
63 end
64 endcase
65
66 endmodule

不好意思,之前忘记把此模块共享了!

此算法是,根据别人的代码学习并修改整理的。








posted on 2011-12-28 23:25  老凯  阅读(4574)  评论(4编辑  收藏  举报