打印

verilog 报错提示求助

[复制链接]
351|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    20:49:28 04/29/2019
// Design Name:
// Module Name:    spi_master
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module spi_master(
                  input         clk_40k,         //clock 40kHz
      input         rst_n,           //reset signal
                  input  [7:0]  data_in,         //from master to slave ,width = 8
                  input      send_start,      //if this signal is high,start communicating, a clock period (40kHz)
                  output [7:0]  data_out,        //from slave to master ,width = 8
                  output  data_out_vld,  //output signal is valid,if this signal is high, a clock period (40kHz)
                  output  cs_n,       //if this signal is low,slave is selected,contain high while communicating
                  output        sclk,            //sync clock,1 kHz,contain low while free
                  input         miso,            //serial data form slave to master
                  output        mosi             //serial data form master to slave
  );
parameter idle        = 2'd0,
          get_address = 2'd1,
    get_data    = 2'd2,
    wait_next   = 2'd3,
    cnt_work_end= 19;  // cnt_work_end = 40/2 -1 =19
reg [2:0]  current_state;
reg [2:0]  next_state;
//state shift
always @ (posedge clk_40k or negedge rst_n)
begin
      if(!rst_n)
          current_state <= idle;
   else
             current_state <= next_state;   
end
//state shifting condition
reg [3:0]  cnt_data;    //to count the number of data that has been transfered
reg [7:0]  data_in_r;   //data_in, register type
reg        flag_low;    //when this signal is valid,start to transfer the r/w and address bits   
reg        flag_high;   //when this signal is valid,start to transfer the r/w and address bits   
reg        mosi_r;      //serial data form master to slave
reg [7:0]  cnt_state;   //to count every sclk,from 0 to 17*4-1 = 67,used for state shifting
reg        work_flag;   //to control a whole period that sends 4 data and read 1 data,when this flag is valid,cnt_state count from 0 to 67
reg [5:0]  cnt_buff_bit;//current number of slave_buff_bit
reg        sclk_r;
always @ (*)
begin
       case(current_state)
       idle:
      begin
            if (send_start)
                            begin      
                                next_state  <= get_address; //start work
                      work_flag   <= 1'b1;        
                                data_in_r   <= data_in;
          flag_low    <= 1'b1;
        sclk_r      <= 1'b1;
        end   
      else
           begin
        cnt_buff_bit<= 6'b0;
                  flag_high  <= 1'b0;
                  mosi_r     <= 1'b0;            
                 next_state  <= idle;
        end
       end
             get_address:
         begin
      if(cnt_buff_bit == 8)
          begin
              next_state <= get_data;
        flag_low   <= 1'b0;
       end
      else
                                next_state <= get_address;      
                  end
      
       get_data:
                  begin
                        if(cnt_buff_bit == 16)
             begin
           next_state <= wait_next;
        flag_high  <= 1'b0;
             end
      else
                              next_state <= get_data;     
                  end      
   
             wait_next:
                  begin
                        case(cnt_state)
          8'd17:   begin  //16*40
                       next_state <= get_address;
           flag_low   <= 1'b1;
          end  
       8'd34:   begin
                         next_state <= get_address;
           flag_low   <= 1'b1;
          end  
                            8'd51:   begin
                         next_state <= get_address;
           flag_low   <= 1'b1;
          end
                            8'd68:   begin  
                         next_state <= get_address;
           flag_low   <= 1'b1;                  
          end  
       8'd85:   begin
                       next_state <= idle;
           flag_low   <= 1'b0;
                                            work_flag  <= 1'b0;
           cnt_state  <= 8'b0;  
                                     end           
                 default:  next_state <= idle;
             endcase  
                  end      

             default:
                        next_state <= idle;   
  endcase         
end

//sync block,to create sclk
reg  [5:0]   cnt_work;
assign sclk = sclk_r;
always @ (posedge clk_40k or negedge rst_n)
begin
        if(!rst_n)
       begin
          sclk_r   <= 1'b0;
                cnt_work <= 6'b0;   
    end
  else
             begin
                  if(work_flag)
            begin     
                          if(cnt_work == cnt_work_end)
           begin        
              cnt_work <= 6'b0;
           sclk_r   <= ~sclk_r;
            end
              else
                             cnt_work <= cnt_work +6'b1;  
                        end
                  else
            begin
            cnt_work <= 6'b0;
         sclk_r   <= 1'b0;
                        end         
             end
end
//delay the work_flag a sclk period later
reg work_flag2;
always @ (posedge sclk or negedge rst_n)
begin
       if(!rst_n)
          work_flag2 <= 1'b0;
    else
             work_flag2 <= work_flag;   
end

//to delay work_flag2 a sclk period later
reg work_flag3;
always @ (posedge sclk or negedge rst_n)
begin
       if(!rst_n)
          work_flag3 <= 1'b0;
    else
             work_flag3 <= work_flag2;   
end
//to delay work_flag3 a sclk period later
reg work_flag4;
always @ (posedge sclk or negedge rst_n)
begin
       if(!rst_n)
          work_flag4 <= 1'b0;
    else
             work_flag4 <= work_flag3;   
end
//sync block,to create cnt_state
always @ (posedge sclk or negedge rst_n)
begin
       if(!rst_n)
          cnt_state <= 8'b0;
    else   
       if(work_flag2)
             cnt_state <= cnt_state + 8'b1;
    else
       cnt_state <= 8'b0;
end

//sync block,to create cnt_buff_bit signal,negedge of sclk
always @ (negedge sclk)
begin
     if(send_start)
              cnt_buff_bit <= 6'b0;
  else
    begin
      if(work_flag4)
           begin
        if(cnt_buff_bit == 6'd16)
        cnt_buff_bit <= 6'b0;
     else
                 cnt_buff_bit <= cnt_buff_bit + 6'b1;     
     end
   else
                 cnt_buff_bit <= 6'b0;   
       end     
end
//sync block cnt_data,which number has been transfered
always @ (posedge sclk or negedge rst_n)
begin
     if(!rst_n)
         cnt_data <= 4'b0;
  else
        begin
     if(work_flag)
             case(cnt_state)
                8'd16:  cnt_data <= cnt_data + 4'b1;
                8'd33:  cnt_data <= cnt_data + 4'b1;  
                8'd50:  cnt_data <= cnt_data + 4'b1;
                8'd67:  cnt_data <= cnt_data + 4'b1;
                default:cnt_data <= cnt_data;
             endcase
          else
                        cnt_data <= 4'b0;   
        end   
end
//reset cnt_data
always @ (posedge clk_40k or rst_n)
begin
     if(!rst_n)
         cnt_data <= 4'b0;
  else
        if(!work_flag)
            cnt_data <= 4'b0;  
end

//the data to reg0 reg1 reg2 and reg3
reg [7:0] data_send;
always @ (posedge sclk or negedge rst_n)
begin
     if(!rst_n)
       data_send <= 8'b00000000;//reset
    else
        begin
          if(work_flag)
             case(cnt_state)
                8'd0 :  data_send <= 8'b00000000;                 //write reg0 address
                8'd7 :  data_send <= data_in;                     //write reg0 data_in
                8'd16:  data_send <= 8'b00000001;                 //write reg1 address
                8'd24:  data_send <= {data_in_r[5:0],data_in_r[7:6]}; //write reg1 rotating left shift 2 data_in
                8'd33:  data_send <= 8'b00000010;                 //write reg2 address
                8'd41:  data_send <= {data_in_r[3:0],data_in_r[7:4]}; //write reg2 rotating left shift 4 data_in
                8'd50:  data_send <= 8'b00000011;                 //write reg3 address
                8'd58:  data_send <= {data_in_r[1:0],data_in_r[7:2]}; //write reg3 rotating left shift 6 data_in
                8'd67:  data_send <= 8'b10000011;                 //read  reg3 address
                8'd75:  data_send <= data_out;                    //read  reg3 data_out
                default:data_send <= data_send;
             endcase
            else
                        data_send <= 8'b0;
        end   
end

endmodule

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

0

帖子

0

粉丝