col(列) = 4 ;line(行) = 5。相邻三行,按列求和。输出新的数据流。
通过rs232通信协议,输入数据流。第一行存进fifo1,第二行存进fifo2.当输入第三行第一个数据的时候,从fifo1和ffo2中读数据,并于当前输入数据相加,并输出结果与标志信号。
1,这个fifo,读写信号同时拉高,我进行功能仿真时,它是写满后,同时拉高,写不进数据。我放一张仿真图:
所以我设计的时序图,fifo1和fifo2都是先读出数据,然后再写数据。
2,数据与标志信号在设计的时候,要注意时序上的对齐。这种小工程,仿真时,时序没问题没问题,上板子后出错,我觉得应该不是时序上的问题(亚稳态)。应该是代码的问题。
因为我在调用之前的uart_rs232模块,修改了参数,结果上板子出错了。就是这个uart模块的问题。苦恼了很久,一开始以为是fifo_sum的问题。我的写法和野火教程里是不完全一样的。
3,大于2的数字,尽量用参数parameter定义。在这方面,吃了大亏(uart模块又花了一个晚上重新写的)。
- module uart_rx(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire rx ,
-
- output reg po_flag ,
- output reg [7:0] po_data
- );
-
- // parameter
- parameter CLK_UART = 50_000_000 ,
- BPS = 9600 ;
- localparam MAX_BPS = CLK_UART / BPS ;
-
- // reg signal define
- reg rx_reg1 ;
- reg rx_reg2 ;
- reg rx_reg3 ;
- wire start ;
- reg work_en ;
- reg [12:0] cnt_bps ;
- reg [ 3:0] cnt_bit ;
- reg bit_flag;
- reg [ 7:0] rx_data ; // 对rx_reg3采样,把串行数据转化为8bit并行数据。
- reg rx_flag ; // 转化完拉高一个时钟周期。
-
-
- /********************************************************/
- // reg rx_reg1 ;
- // reg rx_reg2 ;
- // reg rx_reg3 ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- rx_reg1 <= 1'b1 ; // 由于空闲状态,rx是高电平。
- rx_reg2 <= 1'b1 ;
- rx_reg3 <= 1'b1 ;
- end else begin
- rx_reg1 <= rx ;
- rx_reg2 <= rx_reg1 ;
- rx_reg3 <= rx_reg2 ;
- end
- end
- // reg start ; // 检测到下降沿,拉高一个sys_clk.
- assign start = ~rx_reg2 && rx_reg3 ;
- // reg work_en ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- work_en <= 1'b0 ;
- else if((cnt_bit == 4'd0 && start) || (cnt_bit == 4'd8 && bit_flag)) // 正常来讲,这个两个条件应该是交替出现的。
- work_en <= ~work_en ;
- else
- work_en <= work_en ;
- end
- // reg [12:0] cnt_bps ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- cnt_bps <= 13'd0 ;
- else if(work_en && cnt_bps == (MAX_BPS - 1))
- cnt_bps <= 13'd0 ;
- else if(work_en)
- cnt_bps <= cnt_bps + 1'b1 ;
- else
- cnt_bps <= 13'd0 ;
- end
- // reg bit_flag;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- bit_flag <= 1'b0 ;
- else if(cnt_bps == MAX_BPS - 1) // 波特率计数器的最大值
- bit_flag <= 1'b1 ;
- else
- bit_flag <= 1'b0 ;
- end
- // reg [ 3:0] cnt_bit ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- cnt_bit <= 4'd0 ;
- else if(bit_flag && cnt_bit == 4'd8)
- cnt_bit <= 4'd0 ;
- else if(bit_flag)
- cnt_bit <= cnt_bit + 1'b1 ;
- else
- cnt_bit <= cnt_bit ;
- end
- // reg [ 7:0] rx_data ; // 对rx_reg3采样,把串行数据转化为8bit并行数据。
- // always @(posedge sys_clk or negedge sys_rst_n) begin
- // if(~sys_rst_n)
- // rx_data <= 8'd0 ;
- // else if(work_en == 1'b1 && (cnt_bit >= 1) && (cnt_bps == MAX_BPS/2))
- // rx_data <= {rx_reg3,rx_data[7:1]} ; // 由于rx是先发低位,所以rx_reg3放在前面.右移。
- // else if(work_en == 1'b1 && (cnt_bit >= 1))
- // rx_data <= rx_data ;
- // else
- // rx_data <= rx_data ;
- // end
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- rx_data <= 8'd0 ;
- else if(work_en == 1'b1 && (cnt_bit >= 1)) begin
- if(cnt_bps == MAX_BPS/2)
- rx_data <= {rx_reg3,rx_data[7:1]} ;
- else
- rx_data <= rx_data ;
- end else begin
- rx_data <= rx_data ;
- end
- end
- // reg rx_flag ; // 转化完拉高一个时钟周期。
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- rx_flag <= 1'b0 ;
- else if(cnt_bit == 4'd8 && bit_flag)
- rx_flag <= 1'b1 ;
- else
- rx_flag <= 1'b0 ;
- end
-
- /***********************************************************/
- // output signal
- // po_falg ,
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- po_flag <= 1'b0 ;
- else if(rx_flag) // 可以理解为打一拍子或者使用时序逻辑采样
- po_flag <= 1'b1 ;
- else
- po_flag <= 1'b0 ;
- end
- // po_data
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- po_data <= 8'd0 ;
- else if(rx_flag) // 可以理解为打一拍子或者使用时序逻辑采样
- po_data <= rx_data ;
- else
- po_data <= po_data ; // 可以归零,也可以保持。
- end
- endmodule
- module uart_tx (
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire pi_flag ,
- input wire [7:0] pi_data ,
-
- output reg tx
- );
- // parameter
- parameter SUB_1K = 1000 , // 缩减第十位,空闲位的时间。
- CLK_UART = 50_000_000 ,
- BPS = 9600 ;
- localparam MAX_BPS = CLK_UART / BPS ;
-
- // reg signal define
- reg pi_flag_reg1 ;
- reg [ 7:0] pi_data_reg1 ;
- reg work_en ;
- reg [12:0] cnt_bps ;
- reg [ 3:0] cnt_bit ;
- reg bit_flag ;
-
- /**********************************************/
- // reg pi_flag_reg1 ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- pi_flag_reg1 <= 1'b0 ;
- else
- pi_flag_reg1 <= pi_flag ;
- end
- // reg pi_data_reg1 ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- pi_data_reg1 <= 8'd0 ;
- else
- pi_data_reg1 <= pi_data ;
- end
- // reg work_en ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- work_en <= 1'b0 ;
- else if(((cnt_bit == 4'd0) && pi_flag_reg1) || (cnt_bit == 4'd9) && (bit_flag))
- work_en <= ~work_en ;
- else
- work_en <= work_en ;
- end
- // reg [12:0] cnt_bps ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- cnt_bps <= 13'd0 ;
- else if(work_en && cnt_bps == MAX_BPS - 1) // 波特率计数器计数到最大值。
- cnt_bps <= 13'd0 ;
- else if(work_en)
- cnt_bps <= cnt_bps + 1'b1 ;
- else
- cnt_bps <= 13'd0 ;
- end
- // reg bit_flag ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- bit_flag <= 1'b0 ;
- else if((work_en && cnt_bps == MAX_BPS - 1) || (work_en && cnt_bps == MAX_BPS - SUB_1K && cnt_bit == 9))
- bit_flag <= 1'b1 ;
- else
- bit_flag <= 1'b0 ;
- end
- // reg [ 3:0] cnt_bit ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- cnt_bit <= 4'd0 ;
- else if(work_en && bit_flag && cnt_bit == 4'd9) // 传递完第十位,位计数器要归零。
- cnt_bit <= 4'd0 ;
- else if(work_en && bit_flag)
- cnt_bit <= cnt_bit + 1'b1 ;
- else if(work_en)
- cnt_bit <= cnt_bit ;
- else
- cnt_bit <= 4'd0 ;
- end
- /****************************************/
- // output signal
- // tx
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n)
- tx <= 1'b1 ;
- else if(work_en) begin
- case (cnt_bit)
- 0 : tx <= 1'b0 ;
- 1 : tx <= pi_data_reg1[0] ; // 先发最低位。
- 2 : tx <= pi_data_reg1[1] ;
- 3 : tx <= pi_data_reg1[2] ;
- 4 : tx <= pi_data_reg1[3] ;
- 5 : tx <= pi_data_reg1[4] ;
- 6 : tx <= pi_data_reg1[5] ;
- 7 : tx <= pi_data_reg1[6] ;
- 8 : tx <= pi_data_reg1[7] ;
- 9 : tx <= 1'b1 ;
- default: tx <= 1'b1 ;
- endcase
- end else begin
- tx <= 1'b1 ;
- end
- end
- endmodule
- 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
- );
-
- // parameter
- parameter XLINE_SUM = 3 ,
- MAX_LINE = 5 ,
- MAX_COL = 4 ;
-
- // 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_line >= XLINE_SUM - 1)
- 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_line == 0)
- wrreq1_r <= data_flag ;
- else if((cnt_line == (XLINE_SUM - 1) && cnt_col != 0) || (cnt_line > (XLINE_SUM - 1) && cnt_line <= (MAX_LINE - 2)) || (cnt_line == (MAX_LINE - 1) && cnt_col == 0))
- 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_line == 0)
- dataF1_in_r <= data_in ;
- else if((cnt_line >= (XLINE_SUM - 1) && cnt_line <= (MAX_LINE - 2)) || (cnt_line == (MAX_LINE - 1) && cnt_col == 0))
- 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_line == 1)
- wrreq2_r <= data_flag ;
- else if((cnt_line >= (XLINE_SUM - 1) && cnt_line <= (MAX_LINE - 2)) || (cnt_line == (MAX_LINE - 1) && cnt_col == 0))
- 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_line == 1)
- dataF2_in_r <= data_in ;
- else if((cnt_line >= (XLINE_SUM - 1) && cnt_line <= (MAX_LINE - 2)) || (cnt_line == (MAX_LINE - 1) && cnt_col == 0))
- 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
- module top(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire rx ,
-
- output wire tx
- );
-
- // 例化间连线
- wire po_flag ;
- wire [7:0] po_data ;
- wire sum_flag ;
- wire [7:0] sum_data ;
-
- uart_rx uart_rx_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .rx ( rx ) ,
-
- .po_flag ( po_flag ) ,
- .po_data ( po_data )
- );
-
- fifo_sum fifo_sum_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .data_in ( po_data ) ,
- .data_flag ( po_flag ) ,
-
- .po_data ( sum_data ) ,
- .po_data_falg ( sum_flag )
- );
-
- uart_tx uart_tx_inst(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
- .pi_flag ( sum_flag ) ,
- .pi_data ( sum_data ) ,
-
- .tx ( tx )
- );
-
-
- 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'd2) ;
- rx_bit(8'd2) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd4) ;
- rx_bit(8'd4) ;
- rx_bit(8'd5) ;
- rx_bit(8'd5) ;
- rx_bit(8'd6) ;
- rx_bit(8'd6) ;
- rx_bit(8'd7) ;
- rx_bit(8'd7) ;
- rx_bit(8'd8) ;
- rx_bit(8'd8) ;
- rx_bit(8'd9) ;
- rx_bit(8'd9) ;
- 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'd2) ;
- rx_bit(8'd2) ;
- rx_bit(8'd2) ;
- rx_bit(8'd2) ;
- rx_bit(8'd1) ;
- rx_bit(8'd1) ;
- rx_bit(8'd1) ;
- rx_bit(8'd1) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- rx_bit(8'd3) ;
- $stop ;
- end
- always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
- endmodule
忘记截图了。