RTL综合<2>----for循环

博客探讨了Verilog中for循环的综合问题,通过示例代码和仿真波形展示了在某些情况下,for循环可能无法正确实现预期功能,特别是在涉及前向依赖的结果计算时。建议仅对简单的独立赋值进行综合。

对于现在的仿真器,for循环一般都是可以综合的。


`timescale 1ns / 1ps
module    test(
    input               clk, rst_n,
    input       [7:0]   data,
    output  reg [2:0]   num
);
//=====================================
integer i;
always@(posedge clk)
begin
    if(!rst_n)
        num <= 3'd0;
    else for (i=0; i<8; i=i+1)
            if(data[i])
                num <= num + 1'b1;
end
//====================================
endmodule

这个代码看似是想要在一个时钟周期计算出八位data数据的高电平位数,综合后的电路:
RTL
看着不错,但是真的实现了所要的功能了吗?编写testbench

`timescale 1 ps/ 1 ps
module test_vlg_tst();
reg clk;
reg [7:0] data;
reg rst_n;                                            
wire [2:0]  num;

test i1 (
    .clk(clk),
    .data(data),
    .num(num),
    .rst_n(rst_n)
);
initial                                                
begin                                                  
    rst_n = 0;
    #20 rst_n = 1;
    #500 $stop;
end
initial                                                
begin                                                  
    clk = 0;
    forever #10 clk = ~clk;
end
initial                                                
begin                                                  
    data = 8'hA7;
end
endmodule

仿真波形如下:
sim
可以看出,num只是每个时钟周期加一而已,并不是计算data高电平的位数,always非阻塞赋值,只有always结束后赋值给左边的,因此出现上面情况。将其改为如下:

`timescale 1ns / 1ps
module    test(
    input               clk, rst_n,
    input       [7:0]   data,
    output  reg [7:0]   num
);
//==============================================
integer i;
always@(posedge clk)
begin
    if(!rst_n)
        num = 8'd0;
    else for (i=0; i<8; i=i+1)
            if(data[i])
                num = num + 1'b1;
end
//==============================================
endmodule

仿真波形:
sim


似乎for循环综合这种依赖之前结果的电路会出现问题,一般只建议综合简单的分立的简单赋值:

for (i=0; i<8; i=i+1)
    out[i] <= a[i] & b[i];

<template> <div> <div class="flex gap-5 items-center justify-between m-4"> <div> <el-select v-model="ruleSetName" placeholder="请选择规则集" style="width: 306px" > <el-option v-for="item in ruleSetOptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-text type="primary" class="mx-4 text-[#409eff] self-center" style="padding-bottom: 5px" > {{ usedRulesText }} </el-text> </div> <div> <el-button type="primary" @click="handleSave">保存</el-button> </div> </div> <div class="flex gap-0 p-5 border-t tlinter-border"> <div class="flex flex-col gap-1 w-1/5 h-full"> <div class="w-full h-full py-5 pr-5"> <el-input v-model="searchQuery" placeholder="输入规则编号/描述查询" class="w-full" suffix-icon="Search" clearable /> </div> <div class="flex gap-4"> <el-checkbox-group v-model="selectedLanguages" @change="handleLanguageChange" > <el-checkbox label="VHDL" size="large">VHDL</el-checkbox> <el-checkbox label="Verilog" size="large">Verilog</el-checkbox> </el-checkbox-group> </div> <h1 class="font-inter text-base font-medium leading-[22px] tracking-0 tlinter-text-one pb-2">规则类别</h1> <div class="flex flex-col gap-3"> <div v-for="(category, index) in ruleCategories" :key="index" class="flex items-center p-2 cursor-pointer transition-colors duration-200" :class="{'tlinter-list-selectedfill': category.name === selectedCategory}" @click="selectCategory(category)" > <div class="mr-2"> <checked v-if="hasSelectedRulesInCategory(category.name) && category.name !== selectedCategory"/> <check v-else-if="category.name === selectedCategory"/> <box v-else/> </div> <span class="text-sm tlinter-text-one">{{ category.name }}</span> </div> </div> </div> <div class="flex-1 border-l tlinter-border pl-5 custom-form-item w-4/5"> <el-table ref="ruleTableRef" :data="ruleTable" style="width: 100%" row-key="id" @selection-change="handleSelectionChange" > <el-table-column type="selection" width="55" reserve-selection :selectable="handleSelectable" /> <el-table-column width="400" prop="ruleNo" label="规则编号" > <template #header> <div class="flex items-center gap-2"> <span>规则编号</span> <el-select v-model="headerSelectValue" placeholder="启用状态" style="width: 120px" @change="handleHeaderSelectChange" > <el-option label="已启用" value="enableAll"></el-option> <el-option label="未启用" value="disableAll"></el-option> </el-select> </div> </template> <template #default="scope"> <el-text @click="openDrawer(scope.row)" class="hover:text-primary cursor-pointer" :class="activeRowId === scope.row.id ? 'el-text--primary' : ''" > {{ scope.row.ruleNo }} </el-text> </template> </el-table-column> <el-table-column prop="description" label="描述" width="420" /> <el-table-column prop="alarmType" label="告警类型(点击标签可切换)" > <template #default="scope"> <el-tag :type="getTagType(scope.row.alarmType)" @click="toggleAlarmType(scope.row)" > ● {{ scope.row.alarmType }} </el-tag> </template> </el-table-column> </el-table> </div> </div> <el-drawer v-model="drawerVisible" :title="drawerTitle" size="30%" :before-close="closeDrawer" > <RuleDetails :current-row="currentRow" /> </el-drawer> </div> </template> <script setup> import { ref, computed, reactive, watch, onMounted, nextTick } from 'vue' import { useRouter, useRoute } from 'vue-router' import { ElMessage } from 'element-plus' import RuleDetails from './components/ruleDetails.vue' const router = useRouter() const route = useRoute() const ruleTableRef = ref(null) const headerSelectValue = ref('') const searchQuery = ref('') //VHDL,Verilog多选框 const selectedLanguages = ref([]) // 规则集名称 const ruleSetName = ref('') // 添加当前选中的类别 const selectedCategory = ref('') // 抽屉相关 const drawerVisible = ref(false) const currentRow = ref(null) const drawerTitle = ref('') const activeRowId = ref(null) // 表格选中数据 const selectedRows = ref([]) const ruleSetOptions = ref([ { label: '默认规则集', value: 'default' }, { label: 'RTL语法规则集', value: 'rtl-syntax' }, { label: '综合风格规则集', value: 'synthesis-style' } ]); // 规则类别(左侧筛选) const ruleCategories = ref([ { name: 'VHDL编码规则', language: 'VHDL' }, { name: 'VHDL同步设计规则', language: 'VHDL' }, { name: 'VHDL标头规则', language: 'VHDL' }, { name: 'Verilog编码规则', language: 'Verilog' }, { name: 'Verilog时序规则', language: 'Verilog' }, { name: 'Verilog模块结构规则', language: 'Verilog' }, { name: 'Verilog命名规则', language: 'Verilog' } ]) // 表格原始数据 - 添加更多模拟数据 const ruleData = ref([ // VHDL规则 { id: 1, ruleNo: 'TLR-030001V', description: 'VHDL源文件应包含头注释', alarmType: '错误', category: 'VHDL编码规则', language: 'VHDL', enable: true }, { id: 2, ruleNo: 'TLR-030002V', description: '同步设计应遵循时钟域交叉原则', alarmType: '告警', category: 'VHDL同步设计规则', language: 'VHDL', enable: true }, { id: 3, ruleNo: 'TLR-030003V', description: '标头应包含版本、作者等信息', alarmType: '告警', category: 'VHDL标头规则', language: 'VHDL', enable: false }, { id: 4, ruleNo: 'TLR-030004V', description: '模块端口声明需指定方向(IN/OUT)', alarmType: '错误', category: 'VHDL编码规则', language: 'VHDL', enable: true }, // Verilog规则 { id: 5, ruleNo: 'TLR-040001R', description: 'Verilog模块应有端口声明列表', alarmType: '错误', category: 'Verilog编码规则', language: 'Verilog', enable: true }, { id: 6, ruleNo: 'TLR-040002R', description: '时序逻辑必须使用非阻塞赋值', alarmType: '警告', category: 'Verilog时序规则', language: 'Verilog', enable: true }, { id: 7, ruleNo: 'TLR-040003R', description: '模块应包含module-endmodule结构', alarmType: '错误', category: 'Verilog模块结构规则', language: 'Verilog', enable: true }, { id: 8, ruleNo: 'TLR-040004R', description: '变量命名应使用小写字母加下划线', alarmType: '警告', category: 'Verilog命名规则', language: 'Verilog', enable: false }, { id: 9, ruleNo: 'TLR-040005R', description: '避免使用组合逻辑产生锁存器', alarmType: '错误', category: 'Verilog时序规则', language: 'Verilog', enable: true } ]) // 过滤后的表格数据,添加类别过滤和启用状态过滤 const ruleTable = computed(() => { let filteredData = ruleData.value; // 如果有选中的类别,则进一步过滤 if (selectedCategory.value) { filteredData = filteredData.filter(item => item.category === selectedCategory.value ) } // 搜索过滤 if (searchQuery.value.trim()) { const keyword = searchQuery.value.trim().toLowerCase() filteredData = filteredData.filter(item => item.ruleNo.toLowerCase().includes(keyword) || item.description.toLowerCase().includes(keyword) ) } // 启用状态过滤 if (headerSelectValue.value === 'enableAll') { filteredData = filteredData.filter(item => item.enable) } else if (headerSelectValue.value === 'disableAll') { filteredData = filteredData.filter(item => !item.enable) } return filteredData }) const isAllSelectedEnabled = computed(() => { if (selectedRows.value.length === 0) return false return selectedRows.value.every(row => row.enable === true) }) const usedRulesText = computed(() => { const enabledCount = ruleData.value.filter(rule => rule.enable === true).length return `已启用${enabledCount}条规则` }) const getTagType = computed(() => (alarmType) => { const typeMap = { '错误': 'danger', '告警': 'warning' } return typeMap[alarmType] || 'info' }) // 判断某类别下是否有规则在表格中被选中 const hasSelectedRulesInCategory = computed(() => (categoryName) => { // 遍历表格选中行,检查是否存在该类别的规则 return selectedRows.value.some(row => row.category === categoryName) }) const handleSelectable = (row, index) => { return true; } const handleTableSelection = (tableData) => { if (!ruleTableRef.value || !tableData || tableData.length === 0) { return } // 先清空所有选择 tableData.forEach(row => { ruleTableRef.value.toggleRowSelection(row, false) }) // 根据enable属性设置选择状态 tableData.forEach(row => { if (row.enable) { ruleTableRef.value.toggleRowSelection(row, true) } }) } // 表格选中事件 const handleSelectionChange = (selection) => { selectedRows.value.forEach(row => { const rule = ruleData.value.find(r => r.id === row.id) if (rule) rule.enable = false }) // 将当前选中的规则设为启用 selection.forEach(row => { const rule = ruleData.value.find(r => r.id === row.id) if (rule) rule.enable = true }) selectedRows.value = selection } // 下拉框操作,只控制显示状态,不执行批量操作 const handleHeaderSelectChange = async (value) => { if (value === 'enableAll') { ruleTable.value.forEach(row => { row.enable = true }) } else if (value === 'disableAll') { ruleTable.value.forEach(row => { row.enable = false }) } await nextTick() handleTableSelection(ruleTable.value) } // 切换告警类型 const toggleAlarmType = (row) => { const types = ['错误', '告警'] const currentIdx = types.indexOf(row.alarmType) row.alarmType = types[(currentIdx + 1) % types.length] } // 打开规则详情抽屉 const openDrawer = (row) => { currentRow.value = row drawerTitle.value = row.ruleNo activeRowId.value = row.id drawerVisible.value = true } // 关闭抽屉 const closeDrawer = () => { currentRow.value = null drawerTitle.value = '' activeRowId.value = null drawerVisible.value = false } // 保存规则集 const handleSave = async () => { const savedData = { name: ruleSetName.value, enabledRules: ruleData.value.filter(rule => rule.enable), totalEnabled: ruleData.value.filter(rule => rule.enable).length, updateTime: new Date().toLocaleString() } console.log('保存规则集数据:', savedData) ElMessage.success('规则集保存成功') handlegoback() } // 返回上一页 const handlegoback = () => { router.push("/rules") } // 选择规则类别 const selectCategory = (category) => { // 如果点击已选中的类别,则取消选择 if (selectedCategory.value === category.name) { selectedCategory.value = '' } else { selectedCategory.value = category.name } } // 新增:处理语言变更 const handleLanguageChange = async() => { // 切换语言时重置选中的类别 selectedCategory.value = '' // 处理VHDL语言勾选状态 const isVHDLSelected = selectedLanguages.value.includes('VHDL') ruleData.value.forEach(row => { if (row.language === 'VHDL') { row.enable = isVHDLSelected } }) // 处理Verilog语言勾选状态 const isVerilogSelected = languages.includes('Verilog') ruleData.value.forEach(row => { if (row.language === 'Verilog') { row.enable = isVerilogSelected } }) await nextTick() handleTableSelection(ruleTable.value) } // 监听表格数据变化 watch( () => ruleTable.value, (newTableData) => { handleTableSelection(newTableData) }, { immediate: true, deep: true } ) // 监听选中数据变化 watch( () => selectedRows.value, (newSelected) => { if (isAllSelectedEnabled.value) { headerSelectValue.value = 'enableAll' } else { const validActions = ['enableAll', 'disableAll'] if (!validActions.includes(headerSelectValue.value)) { headerSelectValue.value = '' } } }, { deep: true } ) // 组件挂载完成后,确保表格选中状态初始化 onMounted(async () => { // 默认选择第一个规则类别 if (ruleCategories.value.length > 0) { selectedCategory.value = ruleCategories.value[0].name } await nextTick() handleTableSelection(ruleTable.value) }) </script> <style scoped lang="scss"> :deep(.custom-form-item .el-form-item__content) { margin-left: 20px !important; } // 抽屉样式调整 :deep(.el-drawer__header) { margin-bottom: 0px !important; padding: 16px 24px !important; border-bottom: 1px solid #eee; } // 新增样式:语言选择组 .radio-group-container { display: flex; gap: 16px; margin-bottom: 16px; } // 新增样式:类别项 .category-item { display: flex; align-items: center; padding: 8px 12px; border-radius: 6px; margin-bottom: 8px; cursor: pointer; transition: background-color 0.2s; &:hover { background-color: #f5f7fa; } &.selected { background-color: #ecf5ff; border: 1px solid #d9ecff; } .radio-icon { margin-right: 10px; width: 20px; height: 20px; display: flex; align-items: center; justify-content: center; } } </style>分析代码,取消表格选择框,则代表未启用这条规则,勾选表格选择框,代表勾选了这条规则,"已启用7条规则"实时更新规则,将启用状态下拉框改为,选中未启用时,表格显示未选择的行,选中启用时,表格显示启用行 选中VHDL语言时,规则表格中有关VHDL全部勾选,取消选择VHDL语言时,规则表格中有关VHDL全部取消 每次打开界面时规则类别默认选择第一个 分析代码,完成上述功能分析代码,完善这次功能
最新发布
10-26
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值