拓展训练:
5X5矩阵,按列相邻三个求和。
仍然是以数据流的形式传入数据(rs232),并以数据流的形式传出数据。
分析:
1,其实这个使用两个深度为2的fifo就可以实现了。
并且不再需要行计数器。
每一行,对应列,相关信号变化是一样的,也就是说和行数没有关系。
2,其实这个行与列计数器,就像状态机。只不过用他俩表示矩阵比用状态机表示更方便更直观。
所以我愿称之为"矩阵式状态机"!
3,第一列的数据传给FIFO1,第二列的数据传给fifo2,第三列的数据到来后,fifo的读使能拉高(fifo1和2公用一个读使能信号)。然后读出数据,然后求和标志信号拉高,然后得到和的结果;
在读使能拉高后,fifo2的写使能拉高,然后把第三列的数据写进fifo2;
在fifo2的写使能拉高后,fifo1的写使能拉高,然后把fifo2此时读出的数据写进fifo1(就是对fifo2读出的数采样)至于为什么fifo1的写使能拉高是在fifo2写使能拉高后。我在这里放上一张图片,上面有更直观的是说明:
代码:
只需要改动fifo_sum模块部分代码即可。如下:
module fifo_sum(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [7:0] data_in ,
input wire data_flag ,
output reg [7:0] po_data ,
output reg po_data_falg
);
/*************修改成5行5列矩阵,按列求相邻三列的和****************/
// parameter
parameter XLINE_SUM = 3 ,
MAX_LINE = 5 , // 本实验跟行计数器没有关系。
MAX_COL = 5 ;
// reg signal define
reg [7:0] cnt_line ;
reg [7:0] cnt_col ;
reg rdreq_r ; // fifo1 fifo2 公用一个读使能。
reg wrreq1_r ;
reg [7:0] dataF1_in_r ;
reg wrreq2_r ;
reg [7:0] dataF2_in_r ;
reg [7:0] data_in_reg1;
reg [7:0] data_in_reg2;
reg flag_sum_r ;
// 例化连线
wire rdreq ;
wire [7:0] dataF1_in ;
wire wrreq1 ;
wire empty1 ;
wire full1 ;
wire [7:0] dataF1_out ;
wire [2:0] usedw1 ;
wire [7:0] dataF2_in ;
wire wrreq2 ;
wire empty2 ;
wire full2 ;
wire [7:0] dataF2_out ;
wire [2:0] usedw2 ;
/*************************************************************/
// reg [7:0] cnt_line
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_line <= 8'd0 ;
else if(data_flag && cnt_col == MAX_COL - 1 && cnt_line == MAX_LINE - 1)
cnt_line <= 8'd0 ;
else if(data_flag && cnt_col == MAX_COL - 1)
cnt_line <= cnt_line + 1'b1 ;
else
cnt_line <= cnt_line ;
end
// reg [7:0] cnt_col
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
cnt_col <= 8'd0 ;
else if(data_flag && cnt_col == MAX_COL - 1)
cnt_col <= 8'd0 ;
else if(data_flag)
cnt_col <= cnt_col + 1'b1 ;
else
cnt_col <= cnt_col ;
end
// reg rdreq_r ; // fifo1 fifo2 公用一个读使能。
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
rdreq_r <= 1'b0 ;
else if(cnt_col >= MAX_COL - XLINE_SUM)
rdreq_r <= data_flag ;
else
rdreq_r <= 1'b0 ;
end
// reg wrreq1_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
wrreq1_r <= 1'b0 ;
else if(cnt_col == 0)
wrreq1_r <= data_flag ;
else if(cnt_col >= 3) // 改成大于等于3更具有普适性。
wrreq1_r <= wrreq2_r ;
else
wrreq1_r <= 1'b0 ;
end
// reg [7:0] dataF1_in_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
dataF1_in_r <= 8'd0 ;
else if(cnt_col == 0)
dataF1_in_r <= data_in ;
else if(cnt_col >= 3)
dataF1_in_r <= dataF2_out ;
else
dataF1_in_r <= dataF1_in_r ;
end
// reg wrreq2_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
wrreq2_r <= 1'b0 ;
else if(cnt_col == 1)
wrreq2_r <= data_flag ;
else if(cnt_col >= 2 && cnt_col <= MAX_COL - 2)
wrreq2_r <= rdreq_r ;
end
// reg [7:0] dataF2_in_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
dataF2_in_r <= 8'd0 ;
else if(cnt_col == 1)
dataF2_in_r <= data_in ;
else if(cnt_col >= 2 && cnt_col <= MAX_COL - 2)
dataF2_in_r <= data_in_reg1 ;
else
dataF2_in_r <= dataF2_in_r ;
end
// reg flag_sum_r ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
flag_sum_r <= 1'b0 ;
else
flag_sum_r <= rdreq_r ;
end
/**********************************************************/
// reg [7:0] po_data ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
po_data <= 8'd0 ;
else if(flag_sum_r)
po_data <= dataF1_out + dataF2_out + data_in_reg2 ;
else
po_data <= po_data ;
end
// reg po_data_falg ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n)
po_data_falg <= 1'b0 ;
else if(flag_sum_r)
po_data_falg <=1'b1 ;
else
po_data_falg <= 1'b0 ;
end
// reg [7:0] data_in_reg1;
// reg [7:0] data_in_reg2;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
data_in_reg1 <= 8'd0 ;
data_in_reg2 <= 8'd0 ;
end else begin
data_in_reg1 <= data_in ;
data_in_reg2 <= data_in_reg1 ;
end
end
/*************************************************************/
assign dataF1_in = dataF1_in_r ;
assign wrreq1 = wrreq1_r ;
assign rdreq = rdreq_r ;
assign dataF2_in = dataF2_in_r ;
assign wrreq2 = wrreq2_r ;
fifo_8x8 fifo_8x8_inst1( // 我测试了一下这个fifo 写满了之后读写信号同时拉高,要写的数据不会被写进去。除非有余量才能同时拉高,并且写入数据。
.clock ( sys_clk ) ,
.data ( dataF1_in ) ,
.rdreq ( rdreq ) ,
.wrreq ( wrreq1 ) ,
.empty ( empty1 ) ,
.full ( full1 ) ,
.q ( dataF1_out ) ,
.usedw ( usedw1 )
);
fifo_8x8 fifo_8x8_inst2(
.clock ( sys_clk ) ,
.data ( dataF2_in ) ,
.rdreq ( rdreq ) ,
.wrreq ( wrreq2 ) ,
.empty ( empty2 ) ,
.full ( full2 ) ,
.q ( dataF2_out ) ,
.usedw ( usedw2 )
);
endmodule
仿真模块代码:
`timescale 1ns/1ns
module test_top();
reg sys_clk ;
reg sys_rst_n ;
reg rx ;
wire tx ;
// Instantiation
top top_inst(
.sys_clk ( sys_clk ) ,
.sys_rst_n ( sys_rst_n ) ,
.rx ( rx ) ,
.tx ( tx )
);
parameter CYCLE = 20 ;
defparam top_inst.uart_rx_inst.CLK_UART = 50_000_0 ;
defparam top_inst.uart_tx_inst.CLK_UART = 50_000_0 ;
defparam top_inst.uart_tx_inst.SUB_1K = 10 ;
task rx_bit ;
input [7:0] data ;
integer i ;
for (i = 0;i <= 9 ;i = i + 1 ) begin
case (i)
0: rx <= 1'b0 ;
1: rx <= data[i - 1];
2: rx <= data[i - 1];
3: rx <= data[i - 1];
4: rx <= data[i - 1];
5: rx <= data[i - 1];
6: rx <= data[i - 1];
7: rx <= data[i - 1];
8: rx <= data[i - 1];
9: rx <= 1'b1 ;
default: rx <= 1'b1 ;
endcase
#(CYCLE * 52) ;
end
endtask
initial begin
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
rx <= 1'b1 ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( 210 ) ;
sys_rst_n <= 1'b0 ;
#( 10 ) ;
#( CYCLE * 10 ) ;
sys_rst_n <= 1'b1 ;
#( CYCLE * 100 ) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd2) ;
rx_bit(8'd2) ;
rx_bit(8'd2) ;
rx_bit(8'd2) ;
rx_bit(8'd2) ;
rx_bit(8'd3) ;
rx_bit(8'd3) ;
rx_bit(8'd3) ;
rx_bit(8'd3) ;
rx_bit(8'd3) ;
rx_bit(8'd4) ;
rx_bit(8'd4) ;
rx_bit(8'd4) ;
rx_bit(8'd4) ;
rx_bit(8'd4) ;
rx_bit(8'd5) ;
rx_bit(8'd5) ;
rx_bit(8'd5) ;
rx_bit(8'd5) ;
rx_bit(8'd5) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
rx_bit(8'd1) ;
$stop ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule