硬件数据流从control to FIFO1 to adder to RAM to FIFO2 to control2的 verilog 代码实现 ---- 初版
这是初版的代码 可以提供 一个大概的思路
如果想要处理大数据的话 把 BRAM需要修改 我先做了一个简单的环路 将 地址始终 固定为1
还有 里面内部的各种使能信号 我尽可能 的 完成贴近 握手协议 但是 对于只 传递 一个数据位
并不需要考虑太多此处的问题
我们只展示初步的代码
adder.v
module adder #(
parameter NUMBER1 = 8 ,
parameter NUMBER2 = 8
)(
input [NUMBER1-1 : 0] input1 ,
input [NUMBER2-1 : 0] input2 ,
input clk ,
input rst_n ,
input begin_en ,
output reg finish_en ,
output reg [NUMBER1-1 : 0] out
);
//======================================================================================\
// define parameter and internal signal \
//======================================================================================\
reg [1:0] LCD = 2'b10 ;
reg [1:0] LCD1 ;
//==========================================================================================\
// next is main code \\
//===========================================================================================\\
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
out <= 0 ;
end
else
LCD1 <= LCD ;
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
out <= 0 ;
end
else if(begin_en && finish_en )
begin
out <= input1 + input2 ;
LCD <= {LCD[0],LCD[1]} ;
end
else
out <= out ;
end
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 0)
begin
finish_en <= 1'b1 ;
end
else if(LCD == LCD1)
begin
finish_en <= 1'b1 ;
end
else
finish_en <= 1'b0 ;
end
endmodule
control.v
module control #(
parameter WIDTH = 8
//parameter TKEEP = clogb2(WIDTH)
)(
input sys_clk ,
input sys_rst_n ,
// input [TKEEP-1 : 0] s_keep ,
input tvaild ,
input [WIDTH-1 : 0] din ,
output reg tready ,
output reg [WIDTH-1 : 0] dout ,
output reg wr_en ,
output reg rd_en
);
//=============================================================================\\
// define parameter and internal signals \\
//==============================================================================\\
reg [1:0] LCD = 2'b10 ;
reg [1:0] LCD1 ;
//===============================================================================\\
// next is main code \\
//================================================================================\\
//this is function
function integer clogb2 ;
input [31:0] value ;
begin
value = value - 1 ;
for(clogb2=0;value>0;clogb2=clogb2+1)
value = value >> 1 ;
end
endfunction
//this is build to control for handshake
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
LCD1 <= 0 ;
end
else
LCD1 <= LCD ;
end
// this is for output
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
dout <= 0;
end
else if( tvaild && tready )
begin
dout <= din ;
LCD <= {LCD[0],LCD[1]} ;
end
else
begin
dout <= dout ;
end
end
// this is used to build tready
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
tready <= 1'b1 ;
end
else if(LCD == LCD1)
begin
tready <= 1'b1 ;
end
else
tready<= 1'b0 ;
end
//this is used to wr_en or rd_en
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
wr_en <= 0 ;
//rd_en <= 0 ;
end
else
begin
wr_en<= (tready == 1) ? 1 : 0 ;
// rd_en <= 1 ;
end
end
// i want to build a way let if write that we read
//this is used to rd_en
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
rd_en <= 0 ;
end
else
begin
rd_en <= (wr_en == 1) ? 1 : 0 ;
end
end
endmodule
control2.v
module control2 #(
parameter WIDTH = 8
// parameter KEPBIT = count(WIDTH)
)(
input sys_clk ,
input sys_rst_n ,
input tready1 , // this control2 is used to get from DMA read
input [WIDTH-1 : 0] din ,
// next is output four output
output reg s_tvaild ,
output reg [WIDTH-1 : 0] s_dout ,
output reg s_last
//output reg s_tlast ,
// output reg [KEPBIT-1:0] s_tkeep
);
//=============================================================================\\
// define parameter and internal signals \\
//==============================================================================\\
reg [1:0] LCD = 2'b10 ;
reg [1:0] LCD1 ;
reg [WIDTH-1 : 0] dout1 ;
//===============================================================================\\
// next is main code \\
//================================================================================\\
//this is function
// function integer count ;
// input [31:0] value ;
// begin
// for(count=0;value>0;count=count+1)
// value = value >> 8 ;
// end
// endfunction
//this is build to control for handshake
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
LCD1 <= 0 ;
end
else
LCD1 <= LCD ;
end
// this is for output s_dout
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
s_dout <= 0;
end
else if( s_tvaild && tready1 )
begin
s_dout <= din ;
LCD <= {LCD[0],LCD[1]} ;
end
else
begin
s_dout <= s_dout ;
end
end
// this is used to build s_tvaild
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
s_tvaild <= 1'b1 ;
end
else if(LCD == LCD1)
begin
s_tvaild <= 1'b1 ;
end
else
s_tvaild<= 1'b0 ;
end
// this is what we add to give out
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
s_last <= 0 ;
end
else if(s_dout == dout1 )
begin
s_last <= 1 ;
end
else
s_last <= 0 ;
end
// this is what we add to give last
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
dout1 <= 0 ;
end
else
dout1 <= s_dout ;
end
endmodule
FIFO1.v
//synchronous fifo
module FIFO_syn #(
parameter WIDTH = 16, // the fifo wide
parameter DEPTH = 1024, // deepth
parameter ADDR_WIDTH = clogb2(DEPTH) // bit wide
// parameter PROG_EMPTY = 100, // this what we set to empty
// parameter PROG_FULL = 800 // this what we set to full
)
(
input sys_clk ,
input sys_rst_n ,
input wr_en ,
input rd_en ,
input [WIDTH-1: 0] din ,
output reg full ,
output reg empty , /// 1 is real empty 0 is no empty
output reg [WIDTH-1:0] dout
);
//========================================================================================//
// define parameter and internal signals //
//======================================================================================//
reg [WIDTH-1 : 0] ram[DEPTH-1 : 0] ; // this we set a 15:0 total 1024 number ram
reg [ADDR_WIDTH-1 : 0] wr_addr ; // this is write pointer
reg [ADDR_WIDTH-1 : 0] rd_addr ; // this is read pointer
reg [ADDR_WIDTH-1 : 0] fifo_cnt ;
//=========================================================================================//
// next is main code //
//=========================================================================================//
// we set a function let me to count the number
function integer clogb2; // remember integer has symbol reg has no symbol
input[31:0]value;
begin
value=value-1;
for(clogb2=0;value>0;clogb2=clogb2+1)
value=value>>1;
end
endfunction
// this you can see from the PPT 5-74
//=================================================== next is used to read
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
rd_addr <= {ADDR_WIDTH{1'b0}};
else if(rd_en && !empty)
begin
rd_addr <= rd_addr+1'd1;
dout <= ram[rd_addr];
end
else
begin
rd_addr <= rd_addr;
dout <= dout;
end
end
//=================================================== next is used to write
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
wr_addr <= {ADDR_WIDTH{1'b0}} ; // this let pointer to zero
end
else if( wr_en && !full )
begin // no full and wr_en and whether to write prog_full there
wr_addr <= wr_addr + 1'b1 ;
ram[wr_addr] <= din ;
end
else
wr_addr <= wr_addr ;
end
//============================================================== next is used to set fifo_cnt
always@(posedge sys_clk or negedge sys_rst_n )
begin
if(sys_rst_n == 0)
begin
fifo_cnt <= {ADDR_WIDTH{1'b0}};
end
else if(wr_en && !full && !rd_en)
begin
fifo_cnt <= fifo_cnt + 1'b1 ;
end
else if(rd_en && !empty && !wr_en)
begin
fifo_cnt <= fifo_cnt - 1'b1 ;
end
else
fifo_cnt <= fifo_cnt ;
end
//========================================================== next is empty
// we set counter so when the count is zero empty
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0)
begin
empty <= 1'b1 ; // begin we set empty to high
end
// there is two possibilties first no write fifo_cnt is all zero
//second is no write it will be change to zero is just a will empty signal
else
empty <= (!wr_en && (fifo_cnt[ADDR_WIDTH-1:1] == 'b0))&&((fifo_cnt[0] == 1'b0) || rd_en);
end
//============================================================ next is full
always@(posedge sys_clk or negedge sys_rst_n)
begin
if(sys_rst_n == 0 )
full <= 1'b1;//reset:1
else
full <= (!rd_en && (fifo_cnt[ADDR_WIDTH-1:1]=={(ADDR_WIDTH-1){1'b1}})) && ((fifo_cnt[0] == 1'b1) || wr_en);
end
endmodule
RAM.v
//DUal ended RAM
module RAM #(
parameter WIDTH = 8 ,
parameter DEPTH = 16 ,
parameter ADD_WIDTH = clogb2(DEPTH)
)(
input wr_clk ,
input rd_clk ,
input wr_en ,
input rd_en ,
input [WIDTH-1 : 0 ] din ,
input [ADD_WIDTH-1 : 0] wr_address ,
output reg [WIDTH-1 : 0 ] dout ,
input [ADD_WIDTH-1 : 0] rd_address
);
//==================================================================================\\
// define parameter and internal signal \\
//==================================================================================\\
reg [WIDTH - 1 : 0 ] ram [DEPTH - 1 : 0] ;
//==================================================================================\\
// next is main code \\
//==================================================================================\\
function integer clogb2 ;
input [31:0] value ;
begin
value = value - 1 ;
for(clogb2 = 0 ; value > 0 ; clogb2 = clogb2 + 1)
value = value >> 1 ;
end
endfunction
// write
always@(posedge wr_clk)
begin
if(wr_en) begin
ram[wr_address] <= din ;
end
end
//read
always@(posedge rd_clk)
begin
if(rd_en) begin
dout <= ram[rd_address] ;
end
end
endmodule
top.v
module dig_top #(
parameter CONTROL1_WIDTH = 8 ,
parameter FIFO1_WIDTH = 8 ,
parameter FIFO1_DEPTH = 1024 ,
parameter FIFO1_ADDR_WIDTH = clogb2(FIFO1_DEPTH) ,
parameter NUMBER1 = 8 ,
parameter NUMBER2 = 2 ,
parameter RAM_WIDTH = 8 ,
parameter RAM_DEPTH = 8 ,
parameter RAM_ADDR_WIDTH = clogb2(RAM_DEPTH) ,
parameter FIFO2_WIDTH = 8 ,
parameter FIFO2_DEPTH = 1024 ,
parameter FIFO2_ADDR_WIDTH = clogb2(FIFO1_DEPTH) ,
parameter CONTROL2_WIDTH = 8
)(
input sys_clk ,
input sys_rst_n ,
input tvaild ,
output tready ,
input [CONTROL1_WIDTH-1 : 0] din ,
output [CONTROL2_WIDTH-1 : 0] dout ,
output s_tvaild ,
input s_ready ,
output s_last
);
//====================================================================================\\
// define parameter or internal signals \\
//====================================================================================\\
//control1
wire wr_en ;
wire rd_en ;
wire [CONTROL1_WIDTH - 1 : 0] dout_control ;
wire full ;
wire empty ;
wire [FIFO1_WIDTH - 1 : 0] dout_FIFO ;
wire finish_en ;
wire [RAM_WIDTH - 1 : 0] dout_adder ;
wire [RAM_WIDTH - 1 : 0] dout_RAM ;
wire RAM_rd_en1 ;
wire RAM_rd_en ;
wire FIFO2_full ;
wire FIFO2_empty ;
wire [FIFO2_WIDTH - 1 : 0] dout_FIFO2 ;
//========================================================================================\\
// next is main code \\
//=========================================================================================\\
function integer clogb2 ;
input [31:0] value ;
begin
value = value - 1 ;
for(clogb2 = 0 ; value > 0 ; clogb2 = clogb2 + 1)
value = value >> 1 ;
end
endfunction
//next is control1
control#(
.WIDTH ( CONTROL1_WIDTH )
)u_control(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.tvaild ( tvaild ), // input
.din ( din ), // input
.tready ( tready ), // output
.dout ( dout_control ), //wire
.wr_en ( wr_en ), //wire we set just tready == 1 wr_en
.rd_en ( rd_en ) //wire we set always in 1
);
//next is FIFO1
FIFO_syn#(
.WIDTH ( FIFO1_WIDTH ),
.DEPTH ( FIFO1_DEPTH ),
.ADDR_WIDTH ( FIFO1_ADDR_WIDTH )
)u_FIFO_syn(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.wr_en ( wr_en ),
.rd_en ( rd_en ),
.din ( dout_control ), // from control
.full ( full ),
.empty ( empty ),
.dout ( dout_FIFO ) // this is from FIFO send to adder input1
);
// next is adder
adder#(
.NUMBER1 ( NUMBER1 ),
.NUMBER2 ( NUMBER2 )
)u_adder(
.input1 ( dout_FIFO ), // this is from FIFO
.input2 ( 2'b10 ),
.clk ( sys_clk ),
.rst_n ( sys_rst_n ),
.begin_en ( rd_en ), // this is connect rd_en
.finish_en ( finish_en ),
.out ( dout_adder ) // this is send to bram
);
// there we should add one change the RAM_rd_en
// something should be add
// becasuse we just send one number we should not think the module whether address
// next is BRAM
RAM#(
.WIDTH ( RAM_WIDTH ),
.DEPTH ( RAM_DEPTH ),
.ADD_WIDTH ( RAM_ADDR_WIDTH )
)u_RAM(
.wr_clk ( sys_clk ),
.rd_clk ( sys_clk ),
.wr_en ( finish_en ),
.rd_en ( 1 ), // i think we should set something
.din ( dout_adder ), // the out is from adder
.wr_address ( 1 ), // i just set one way so we put address just a set value
.dout ( dout_RAM ),
.rd_address ( 1 )
);
//next is FIFO2
FIFO_syn#(
.WIDTH ( FIFO2_WIDTH ),
.DEPTH ( FIFO2_DEPTH ),
.ADDR_WIDTH ( FIFO2_ADDR_WIDTH )
)u_FIFO_syn2(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.wr_en ( 1 ), // we should pay attention to this wr_en or rd_en
.rd_en ( 1 ),
.din ( dout_RAM ),
.full ( FIFO2_full ),
.empty ( FIFO2_empty ),
.dout ( dout_FIFO2 )
);
// next is control
control2#(
.WIDTH ( CONTROL2_WIDTH )
)u_control2(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.tready1 ( s_ready ),
.din ( dout_FIFO2 ),
.s_tvaild ( s_tvaild ),
.s_dout ( dout ),
.s_last ( s_last )
);
endmodule
top_tb.v
`timescale 1ns/1ps
module top_tb #(
parameter CONTROL1_WIDTH = 4 ,
parameter FIFO1_WIDTH = 4 ,
parameter FIFO1_DEPTH = 8 ,
parameter FIFO1_ADDR_WIDTH = 3 ,
parameter NUMBER1 = 4 ,
parameter NUMBER2 = 2 ,
parameter RAM_WIDTH = 4 ,
parameter RAM_DEPTH = 8 ,
parameter RAM_ADDR_WIDTH = 3 ,
parameter FIFO2_WIDTH = 4 ,
parameter FIFO2_DEPTH = 8 ,
parameter FIFO2_ADDR_WIDTH = 3 ,
parameter CONTROL2_WIDTH = 4
);
reg sys_clk ;
reg sys_rst_n ;
reg tvaild ;
wire tready ;
reg [CONTROL1_WIDTH-1 : 0] din ;
wire [CONTROL2_WIDTH-1 : 0] dout ;
wire s_tvaild ;
reg s_ready ;
wire s_last ;
dig_top#(
.CONTROL1_WIDTH ( CONTROL1_WIDTH ),
.FIFO1_WIDTH ( FIFO1_WIDTH ),
.FIFO1_DEPTH ( FIFO1_DEPTH ),
.FIFO1_ADDR_WIDTH ( FIFO1_ADDR_WIDTH ),
.NUMBER1 ( NUMBER1 ),
.NUMBER2 ( NUMBER2 ),
.RAM_WIDTH ( RAM_WIDTH ),
.RAM_DEPTH ( RAM_DEPTH ),
.RAM_ADDR_WIDTH ( RAM_ADDR_WIDTH ),
.FIFO2_WIDTH ( FIFO2_WIDTH ),
.FIFO2_DEPTH ( FIFO2_DEPTH ),
.FIFO2_ADDR_WIDTH ( FIFO2_ADDR_WIDTH ),
.CONTROL2_WIDTH ( CONTROL2_WIDTH )
)u_dig_top(
.sys_clk ( sys_clk ),
.sys_rst_n ( sys_rst_n ),
.tvaild ( tvaild ),
.tready ( tready ),
.din ( din ),
.dout ( dout ),
.s_tvaild ( s_tvaild ),
.s_ready ( s_ready ),
.s_last ( s_last )
);
//input sys_clk ,
//input sys_rst_n ,
//input tvaild ,
//input [CONTROL1_WIDTH-1 : 0] din ,
//input s_ready ,
always #5 sys_clk = ~sys_clk ;
initial begin
sys_clk = 0 ;
sys_rst_n = 1 ;
tvaild = 0 ;
din = 4'b0010 ;
s_ready = 0 ;
#10
sys_rst_n = 1 ;
#10
sys_rst_n = 0 ;
#10
sys_rst_n = 1 ;
tvaild = 1;
din = 4'b0110 ;
s_ready = 1 ;
end
endmodule